diff --git a/include/picrin.h b/include/picrin.h index 2867439a..ea7d3228 100644 --- a/include/picrin.h +++ b/include/picrin.h @@ -166,6 +166,9 @@ char *pic_strdup(pic_state *, const char *); char *pic_strndup(pic_state *, const char *, size_t); struct pic_string *pic_str_new(pic_state *, const char *, size_t); /* the 2nd arg may be NULL for empty string */ struct pic_string *pic_str_new_cstr(pic_state *, const char *); +pic_value pic_format(pic_state *, const char *, ...); +pic_value pic_vformat(pic_state *, const char *, va_list); +pic_value pic_vfformat(pic_state *, XFILE *, const char *, va_list); struct pic_vector *pic_vec_new(pic_state *, size_t); struct pic_vector *pic_vec_new_from_list(pic_state *, pic_value); diff --git a/src/error.c b/src/error.c index 5e6fee08..c375f36c 100644 --- a/src/error.c +++ b/src/error.c @@ -8,8 +8,6 @@ #include "picrin.h" #include "picrin/pair.h" -#include "picrin/proc.h" -#include "picrin/port.h" #include "picrin/error.h" const char * @@ -20,86 +18,6 @@ pic_errmsg(pic_state *pic) return pic->err->msg->str; } -static pic_value -pic_vfformat(pic_state *pic, XFILE *file, const char *fmt, va_list ap) -{ - char c; - pic_value irrs = pic_nil_value(); - - while ((c = *fmt++)) { - switch (c) { - default: - xfputc(c, file); - break; - case '%': - c = *fmt++; - if (! c) - goto exit; - switch (c) { - default: - xfputc(c, file); - break; - case '%': - xfputc('%', file); - break; - case 'c': - xfprintf(file, "%c", va_arg(ap, int)); - break; - case 's': - xfprintf(file, "%s", va_arg(ap, const char *)); - break; - case 'd': - xfprintf(file, "%d", va_arg(ap, int)); - break; - case 'p': - xfprintf(file, "%p", va_arg(ap, void *)); - break; - case 'f': - xfprintf(file, "%f", va_arg(ap, double)); - break; - } - break; - case '~': - c = *fmt++; - if (! c) - goto exit; - switch (c) { - default: - xfputc(c, file); - break; - case '~': - xfputc('~', file); - break; - case '%': - xfputc('\n', file); - break; - case 'S': - irrs = pic_cons(pic, pic_fdebug(pic, va_arg(ap, pic_value), file), irrs); - break; - } - break; - } - } - exit: - - return pic_reverse(pic, irrs); -} - -static pic_value -pic_vformat(pic_state *pic, const char *fmt, va_list ap) -{ - struct pic_port *port; - pic_value irrs; - - port = pic_open_output_string(pic); - - irrs = pic_vfformat(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; -} - NORETURN static void error(pic_state *pic, struct pic_string *msg, pic_value irrs) { diff --git a/src/string.c b/src/string.c index 2c44c415..67b98692 100644 --- a/src/string.c +++ b/src/string.c @@ -5,6 +5,8 @@ #include #include "picrin.h" +#include "picrin/pair.h" +#include "picrin/port.h" struct pic_string * pic_str_new(pic_state *pic, const char *cstr, size_t len) @@ -24,6 +26,99 @@ pic_str_new(pic_state *pic, const char *cstr, size_t len) return str; } +pic_value +pic_vfformat(pic_state *pic, XFILE *file, const char *fmt, va_list ap) +{ + char c; + pic_value irrs = pic_nil_value(); + + while ((c = *fmt++)) { + switch (c) { + default: + xfputc(c, file); + break; + case '%': + c = *fmt++; + if (! c) + goto exit; + switch (c) { + default: + xfputc(c, file); + break; + case '%': + xfputc('%', file); + break; + case 'c': + xfprintf(file, "%c", va_arg(ap, int)); + break; + case 's': + xfprintf(file, "%s", va_arg(ap, const char *)); + break; + case 'd': + xfprintf(file, "%d", va_arg(ap, int)); + break; + case 'p': + xfprintf(file, "%p", va_arg(ap, void *)); + break; + case 'f': + xfprintf(file, "%f", va_arg(ap, double)); + break; + } + break; + case '~': + c = *fmt++; + if (! c) + goto exit; + switch (c) { + default: + xfputc(c, file); + break; + case '~': + xfputc('~', file); + break; + case '%': + xfputc('\n', file); + break; + case 'S': + irrs = pic_cons(pic, pic_fdebug(pic, va_arg(ap, pic_value), file), irrs); + break; + } + break; + } + } + exit: + + return pic_reverse(pic, irrs); +} + +pic_value +pic_vformat(pic_state *pic, const char *fmt, va_list ap) +{ + struct pic_port *port; + pic_value irrs; + + port = pic_open_output_string(pic); + + irrs = pic_vfformat(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_value +pic_format(pic_state *pic, const char *fmt, ...) +{ + va_list ap; + pic_value objs; + + va_start(ap, fmt); + objs = pic_vformat(pic, fmt, ap); + va_end(ap); + + return objs; +} + struct pic_string * pic_str_new_cstr(pic_state *pic, const char *cstr) {