diff --git a/include/picrin/string.h b/include/picrin/string.h index 66ccd374..f2058cde 100644 --- a/include/picrin/string.h +++ b/include/picrin/string.h @@ -22,7 +22,10 @@ pic_str *pic_str_new(pic_state *, const char * /* nullable */, size_t); pic_str *pic_str_new_cstr(pic_state *, const char *); pic_str *pic_str_new_fill(pic_state *, size_t, char); +size_t pic_strlen(pic_state *, pic_str *); char pic_str_ref(pic_state *, pic_str *, size_t); +void pic_str_set(pic_state *, pic_str *, size_t, char); + pic_str *pic_strcat(pic_state *, pic_str *, pic_str *); pic_str *pic_substr(pic_state *, pic_str *, size_t, size_t); diff --git a/src/error.c b/src/error.c index 8faa359f..81cc3403 100644 --- a/src/error.c +++ b/src/error.c @@ -167,16 +167,16 @@ pic_error_raise_continuable(pic_state *pic) NORETURN static pic_value pic_error_error(pic_state *pic) { - char *str; - size_t len, argc; + pic_str *str; + size_t argc; pic_value *argv; struct pic_error *e; - pic_get_args(pic, "s*", &str, &len, &argc, &argv); + pic_get_args(pic, "s*", &str, &argc, &argv); e = (struct pic_error *)pic_obj_alloc(pic, sizeof(struct pic_error), PIC_TT_ERROR); e->type = PIC_ERROR_OTHER; - e->msg = pic_str_new_cstr(pic, str); + e->msg = str; e->irrs = pic_list_by_array(pic, argc, argv); pic_raise(pic, e); diff --git a/src/file.c b/src/file.c index 50f7a646..c68a1869 100644 --- a/src/file.c +++ b/src/file.c @@ -29,9 +29,8 @@ pic_file_open_input_file(pic_state *pic) { static const short flags = PIC_PORT_IN | PIC_PORT_TEXT; char *fname; - size_t size; - pic_get_args(pic, "s", &fname, &size); + pic_get_args(pic, "z", &fname); return generic_open_file(pic, fname, "r", flags); } @@ -41,9 +40,8 @@ pic_file_open_input_binary_file(pic_state *pic) { static const short flags = PIC_PORT_IN | PIC_PORT_BINARY; char *fname; - size_t size; - pic_get_args(pic, "s", &fname, &size); + pic_get_args(pic, "z", &fname); return generic_open_file(pic, fname, "rb", flags); } @@ -53,9 +51,8 @@ pic_file_open_output_file(pic_state *pic) { static const short flags = PIC_PORT_OUT | PIC_PORT_TEXT; char *fname; - size_t size; - pic_get_args(pic, "s", &fname, &size); + pic_get_args(pic, "z", &fname); return generic_open_file(pic, fname, "w", flags); } @@ -65,9 +62,8 @@ pic_file_open_output_binary_file(pic_state *pic) { static const short flags = PIC_PORT_OUT | PIC_PORT_BINARY; char *fname; - size_t size; - pic_get_args(pic, "s", &fname, &size); + pic_get_args(pic, "z", &fname); return generic_open_file(pic, fname, "wb", flags); } @@ -76,10 +72,9 @@ pic_value pic_file_exists_p(pic_state *pic) { char *fname; - size_t size; FILE *fp; - pic_get_args(pic, "s", &fname, &size); + pic_get_args(pic, "z", &fname); fp = fopen(fname, "r"); if (fp) { @@ -94,9 +89,8 @@ pic_value pic_file_delete(pic_state *pic) { char *fname; - size_t size; - pic_get_args(pic, "s", &fname, &size); + pic_get_args(pic, "z", &fname); if (remove(fname) != 0) { pic_error(pic, "file cannot be deleted"); diff --git a/src/load.c b/src/load.c index 84fc7c29..75d13749 100644 --- a/src/load.c +++ b/src/load.c @@ -48,9 +48,8 @@ pic_load_load(pic_state *pic) { pic_value envid; char *fn; - size_t len; - pic_get_args(pic, "s|o", &fn, &len, &envid); + pic_get_args(pic, "z|o", &fn, &envid); return pic_load(pic, fn); } diff --git a/src/port.c b/src/port.c index 0295ff24..2f460d82 100644 --- a/src/port.c +++ b/src/port.c @@ -4,6 +4,7 @@ #include #include +#include #include "picrin.h" #include "picrin/proc.h" @@ -264,9 +265,8 @@ pic_port_open_input_string(pic_state *pic) { struct pic_port *port; char *str; - size_t len; - pic_get_args(pic, "s", &str, &len); + pic_get_args(pic, "z", &str); port = (struct pic_port *)pic_obj_alloc(pic, sizeof(struct pic_port *), PIC_TT_PORT); port->file = xmopen(); @@ -465,23 +465,22 @@ static pic_value pic_port_write_string(pic_state *pic) { char *str; - size_t len; struct pic_port *port; int start, end, n, i; - n = pic_get_args(pic, "s|pii", &str, &len, &port, &start, &end); + n = pic_get_args(pic, "z|pii", &str, &port, &start, &end); switch (n) { case 1: port = pic_stdout(pic); case 2: start = 0; case 3: - end = len; + end = INT_MAX; } assert_port_profile(port, PIC_PORT_OUT | PIC_PORT_TEXT, PIC_PORT_OPEN, "write-string"); - for (i = start; i < end; ++i) { + for (i = start; i < end && str[i] != '\0'; ++i) { xfputc(str[i], port->file); } return pic_none_value(); diff --git a/src/string.c b/src/string.c index d35bedfb..56e6c78f 100644 --- a/src/string.c +++ b/src/string.c @@ -48,6 +48,14 @@ pic_str_new_fill(pic_state *pic, size_t len, char fill) return pic_str_new(pic, cstr, len); } +size_t +pic_strlen(pic_state *pic, pic_str *str) +{ + UNUSED(pic); + + return str->len; +} + char pic_str_ref(pic_state *pic, pic_str *str, size_t n) { @@ -56,6 +64,14 @@ pic_str_ref(pic_state *pic, pic_str *str, size_t n) return str->str[n]; } +void +pic_str_set(pic_state *pic, pic_str *str, size_t i, char c) +{ + UNUSED(pic); + + str->str[i] = c; +} + pic_str * pic_strcat(pic_state *pic, pic_str *a, pic_str *b) { @@ -204,36 +220,34 @@ pic_str_make_string(pic_state *pic) static pic_value pic_str_string_length(pic_state *pic) { - char *str; - size_t len; + pic_str *str; - pic_get_args(pic, "s", &str, &len); + pic_get_args(pic, "s", &str); - return pic_int_value(len); + return pic_int_value(pic_strlen(pic, str)); } static pic_value pic_str_string_ref(pic_state *pic) { - char *str; - size_t len; + pic_str *str; int k; - pic_get_args(pic, "si", &str, &len, &k); + pic_get_args(pic, "si", &str, &k); - return pic_char_value(str[k]); + return pic_char_value(pic_str_ref(pic, str, k)); } static pic_value pic_str_string_set(pic_state *pic) { - char *str, c; - size_t len; + pic_str *str; + char c; int k; - pic_get_args(pic, "sic", &str, &len, &k, &c); + pic_get_args(pic, "sic", &str, &k, &c); - str[k] = c; + pic_str_set(pic, str, k, c); return pic_none_value(); } @@ -273,45 +287,38 @@ DEFINE_STRING_CMP(ge, >=) static pic_value pic_str_string_copy(pic_state *pic) { - size_t len; - char *str; - int n, start, end, i; - pic_str *copy; + pic_str *str; + int n, start, end; - n = pic_get_args(pic, "s|ii", &str, &len, &start, &end); + n = pic_get_args(pic, "s|ii", &str, &start, &end); switch (n) { case 1: start = 0; case 2: - end = len; + end = pic_strlen(pic, str); } - copy = pic_str_new(pic, NULL, end - start); - for (i = 0; i < end - start; ++i) { - copy->str[i] = str[start + i]; - } - return pic_obj_value(copy); + return pic_obj_value(pic_substr(pic, str, start, end)); } static pic_value pic_str_string_copy_ip(pic_state *pic) { - size_t to_len, from_len; - char *to_str, *from_str; + pic_str *to, *from; int n, at, start, end; - n = pic_get_args(pic, "sis|ii", &to_str, &to_len, &at, &from_str, &from_len, &start, &end); + n = pic_get_args(pic, "sis|ii", &to, &at, &from, &start, &end); switch (n) { case 3: start = 0; case 4: - end = from_len; + end = pic_strlen(pic, from); } while (start < end) { - to_str[at++] = from_str[start++]; + pic_str_set(pic, to, at++, pic_str_ref(pic, from, start++)); } return pic_none_value(); } @@ -319,44 +326,40 @@ pic_str_string_copy_ip(pic_state *pic) static pic_value pic_str_string_append(pic_state *pic) { - size_t argc, len, i; + size_t argc, i; pic_value *argv; - char *buf; + pic_str *str; pic_get_args(pic, "*", &argc, &argv); - len = 0; - buf = NULL; + str = pic_str_new(pic, NULL, 0); for (i = 0; i < argc; ++i) { if (! pic_str_p(argv[i])) { pic_error(pic, "type error"); } - buf = pic_realloc(pic, buf, len + pic_str_ptr(argv[i])->len); - /* copy! */ - memcpy(buf + len, pic_str_ptr(argv[i])->str, pic_str_ptr(argv[i])->len); - len += pic_str_ptr(argv[i])->len; + str = pic_strcat(pic, str, pic_str_ptr(argv[i])); } - return pic_obj_value(pic_str_new(pic, buf, len)); + return pic_obj_value(str); } static pic_value pic_str_string_fill_ip(pic_state *pic) { - size_t len; - char *str, c; + pic_str *str; + char c; int n, start, end; - n = pic_get_args(pic, "sc|ii", &str, &len, &c, &start, &end); + n = pic_get_args(pic, "sc|ii", &str, &c, &start, &end); switch (n) { case 1: start = 0; case 2: - end = len; + end = pic_strlen(pic, str); } while (start < end) { - str[start++] = c; + pic_str_set(pic, str, start++, c); } return pic_none_value(); } diff --git a/src/system.c b/src/system.c index be814089..afe4301a 100644 --- a/src/system.c +++ b/src/system.c @@ -83,9 +83,8 @@ static pic_value pic_system_getenv(pic_state *pic) { char *str, *val; - size_t len; - pic_get_args(pic, "s", &str, &len); + pic_get_args(pic, "z", &str); val = getenv(str); diff --git a/src/vm.c b/src/vm.c index 2bd8f27e..02675ba3 100644 --- a/src/vm.c +++ b/src/vm.c @@ -170,19 +170,33 @@ pic_get_args(pic_state *pic, const char *format, ...) break; } case 's': { + pic_str **str; + pic_value v; + + str = va_arg(ap, pic_str **); + if (i < argc) { + v = GET_OPERAND(pic,i); + if (pic_str_p(v)) { + *str = pic_str_ptr(v); + } + else { + pic_error(pic, "pic_get_args: expected string"); + } + i++; + } + break; + } + case 'z': { pic_value str; char **cstr; - size_t *len; cstr = va_arg(ap, char **); - len = va_arg(ap, size_t *); if (i < argc) { str = GET_OPERAND(pic,i); if (! pic_str_p(str)) { pic_error(pic, "pic_get_args: expected string"); } *cstr = pic_str_ptr(str)->str; - *len = pic_str_ptr(str)->len; i++; } break;