reimplement pic_strf_value

This commit is contained in:
Yuichi Nishiwaki 2017-05-10 22:35:31 +09:00
parent aa4f94e378
commit cbec7646c0
6 changed files with 139 additions and 104 deletions

View File

@ -123,6 +123,34 @@ pic_file_open_output_file(pic_state *pic)
return pic_fopen(pic, fp, "w");
}
pic_value
pic_file_open_binary_input_file(pic_state *pic)
{
const char *fname;
FILE *fp;
pic_get_args(pic, "z", &fname);
if ((fp = fopen(fname, "rb")) == NULL) {
file_error(pic, "could not open file", 1, pic_cstr_value(pic, fname));
}
return pic_fopen(pic, fp, "rb");
}
pic_value
pic_file_open_binary_output_file(pic_state *pic)
{
const char *fname;
FILE *fp;
pic_get_args(pic, "z", &fname);
if ((fp = fopen(fname, "wb")) == NULL) {
file_error(pic, "could not open file", 1, pic_cstr_value(pic, fname));
}
return pic_fopen(pic, fp, "wb");
}
pic_value
pic_file_exists_p(pic_state *pic)
{
@ -154,13 +182,21 @@ pic_file_delete(pic_state *pic)
void
pic_init_file(pic_state *pic)
{
pic_defvar(pic, "current-input-port", pic_fopen(pic, stdin, "r"));
pic_defvar(pic, "current-output-port", pic_fopen(pic, stdout, "w"));
pic_defvar(pic, "current-error-port", pic_fopen(pic, stdout, "w"));
pic_value i, o, e;
i = pic_fopen(pic, stdin, "r");
o = pic_fopen(pic, stdout, "w");
e = pic_fopen(pic, stderr, "w");
pic_setvbuf(pic, i, NULL, PIC_IOLBF, 0);
pic_setvbuf(pic, o, NULL, PIC_IOLBF, 0);
pic_defvar(pic, "current-input-port", i);
pic_defvar(pic, "current-output-port", o);
pic_defvar(pic, "current-error-port", e);
pic_defun(pic, "open-input-file", pic_file_open_input_file);
pic_defun(pic, "open-output-file", pic_file_open_output_file);
pic_defun(pic, "open-binary-input-file", pic_file_open_input_file);
pic_defun(pic, "open-binary-output-file", pic_file_open_output_file);
pic_defun(pic, "open-binary-input-file", pic_file_open_binary_input_file);
pic_defun(pic, "open-binary-output-file", pic_file_open_binary_output_file);
pic_defun(pic, "file-exists?", pic_file_exists_p);
pic_defun(pic, "delete-file", pic_file_delete);
}

View File

@ -17,10 +17,12 @@ main(int argc, char *argv[])
if (argc == 1) { /* repl */
while (1) {
pic_printf(pic, "> ");
pic_fflush(pic, pic_stdout(pic));
e = pic_funcall(pic, "read", 0);
if (pic_eof_p(pic, e))
break;
pic_printf(pic, "~s\n", pic_funcall(pic, "eval", 1, e));
pic_funcall(pic, "write", 1, pic_funcall(pic, "eval", 1, e));
pic_printf(pic, "\n");
}
} else if (argc == 2) { /* load file */
FILE *file = fopen(argv[1], "r");

View File

@ -258,6 +258,10 @@ typedef struct {
#define PIC_SEEK_END 1
#define PIC_SEEK_SET 2
#define PIC_IONBF 0
#define PIC_IOLBF 1
#define PIC_IOFBF 2
#define pic_stdin(pic) pic_funcall(pic, "current-input-port", 0)
#define pic_stdout(pic) pic_funcall(pic, "current-output-port", 0)
#define pic_stderr(pic) pic_funcall(pic, "current-error-port", 0)
@ -281,13 +285,11 @@ int pic_fputs(pic_state *, const char *s, pic_value port);
char *pic_fgets(pic_state *, char *s, int size, pic_value port);
int pic_ungetc(pic_state *, int c, pic_value port);
int pic_fflush(pic_state *, pic_value port);
int pic_setvbuf(pic_state *, pic_value port, char *buf, int mode, size_t size);
/* formatted output */
int pic_printf(pic_state *, const char *fmt, ...);
int pic_fprintf(pic_state *, pic_value port, const char *fmt, ...);
int pic_vfprintf(pic_state *, pic_value port, const char *fmt, va_list ap);
/* string buffer */
pic_value pic_fmemopen(pic_state *, const char *buf, int len, const char *mode); /* deprecated */
int pic_fgetbuf(pic_state *, pic_value port, const char **buf, int *len); /* deprecated */
/*

View File

@ -129,12 +129,13 @@ struct proc {
};
enum {
FILE_READ = 01,
FILE_WRITE = 02,
FILE_UNBUF = 04,
FILE_EOF = 010,
FILE_ERR = 020,
FILE_LNBUF = 040
FILE_READ = 01,
FILE_WRITE = 02,
FILE_UNBUF = 04,
FILE_EOF = 010,
FILE_ERR = 020,
FILE_LNBUF = 040,
FILE_SETBUF = 0100
};
struct port {

View File

@ -35,13 +35,13 @@ pic_fclose(pic_state *pic, pic_value port)
return 0;
pic_fflush(pic, port);
fp->flag = 0;
if (fp->base != fp->buf)
if (fp->base != fp->buf && (fp->flag & FILE_SETBUF) == 0)
pic_free(pic, fp->base);
return fp->vtable->close(pic, fp->cookie);
}
void
pic_clearerr(pic_state *PIC_UNUSED(pic), pic_value port)
pic_clearerr(pic_state *pic, pic_value port)
{
struct file *fp = &port_ptr(pic, port)->file;
@ -49,7 +49,7 @@ pic_clearerr(pic_state *PIC_UNUSED(pic), pic_value port)
}
int
pic_feof(pic_state *PIC_UNUSED(pic), pic_value port)
pic_feof(pic_state *pic, pic_value port)
{
struct file *fp = &port_ptr(pic, port)->file;
@ -57,13 +57,36 @@ pic_feof(pic_state *PIC_UNUSED(pic), pic_value port)
}
int
pic_ferror(pic_state *PIC_UNUSED(pic), pic_value port)
pic_ferror(pic_state *pic, pic_value port)
{
struct file *fp = &port_ptr(pic, port)->file;
return (fp->flag & FILE_ERR) != 0;
}
int
pic_setvbuf(pic_state *pic, pic_value port, char *buf, int mode, size_t size)
{
struct file *fp = &port_ptr(pic, port)->file;
fp->flag &= ~(FILE_UNBUF | FILE_LNBUF);
if (mode == PIC_IOLBF) {
fp->flag |= FILE_LNBUF;
} else if (mode == PIC_IONBF) {
fp->flag |= FILE_UNBUF;
}
if (buf == NULL) {
return 0;
}
if (size != PIC_BUFSIZ) {
return EOF;
}
fp->base = buf;
fp->flag |= FILE_SETBUF;
return 0;
}
static int
fillbuf(pic_state *pic, struct file *fp)
{
@ -230,7 +253,7 @@ pic_fgets(pic_state *pic, char *s, int size, pic_value port)
}
int
pic_ungetc(pic_state *PIC_UNUSED(pic), int c, pic_value port)
pic_ungetc(pic_state *pic, int c, pic_value port)
{
struct file *fp = &port_ptr(pic, port)->file;
unsigned char uc = c;
@ -311,79 +334,7 @@ pic_fseek(pic_state *pic, pic_value port, long offset, int whence)
int
pic_vfprintf(pic_state *pic, pic_value port, const char *fmt, va_list ap)
{
const char *p;
long start = pic_fseek(pic, port, 0, PIC_SEEK_CUR);
for (p = fmt; *p; p++) {
if (*p == '~') {
switch (*++p) {
default:
pic_fputc(pic, *(p-1), port);
break;
case '%':
pic_fputc(pic, '\n', port);
break;
case 'a':
pic_void(pic, pic_funcall(pic, "display", 2, va_arg(ap, pic_value), port));
break;
case 's':
pic_void(pic, pic_funcall(pic, "write", 2, va_arg(ap, pic_value), port));
break;
}
continue;
}
if (*p == '%') {
switch (*++p) {
case 'd':
case 'i': {
int ival = va_arg(ap, int);
pic_value str = pic_funcall(pic, "number->string", 1, pic_int_value(pic, ival));
pic_fputs(pic, pic_cstr(pic, str, 0), port);
break;
}
case 'f': {
double f = va_arg(ap, double);
pic_value str = pic_funcall(pic, "number->string", 1, pic_float_value(pic, f));
pic_fputs(pic, pic_cstr(pic, str, 0), port);
break;
}
case 'c': {
int ival = va_arg(ap, int);
pic_fputc(pic, ival, port);
break;
}
case 's': {
char *sval = va_arg(ap, char*);
pic_fputs(pic, sval, port);
break;
}
case 'p': {
static const char digits[] = "0123456789abcdef";
unsigned long vp = (unsigned long) va_arg(ap, void*);
char buf[sizeof vp * CHAR_BIT / 4 + 1];
size_t i;
for (i = 0; i < sizeof buf - 1; ++i) {
buf[sizeof buf - i - 2] = digits[vp % 16];
vp /= 16;
}
buf[i] = '\0';
pic_fputs(pic, "0x", port);
pic_fputs(pic, buf, port);
break;
}
case '%':
pic_fputc(pic, *(p-1), port);
break;
default:
pic_fputc(pic, '%', port);
pic_fputc(pic, *(p-1), port);
break;
}
continue;
}
pic_fputc(pic, *p, port);
}
return pic_fseek(pic, port, 0, PIC_SEEK_CUR) - start;
return pic_fputs(pic, pic_cstr(pic, pic_vstrf_value(pic, fmt, ap), NULL), port);
}
int

View File

@ -229,24 +229,67 @@ pic_strf_value(pic_state *pic, const char *fmt, ...)
va_start(ap, fmt);
str = pic_vstrf_value(pic, fmt, ap);
va_end(ap);
return str;
}
pic_value
pic_vstrf_value(pic_state *pic, const char *fmt, va_list ap)
{
pic_value str, port;
const char *buf;
int len;
pic_value str, str2;
const char *p;
port = pic_fmemopen(pic, NULL, 0, "w");
pic_vfprintf(pic, port, fmt, ap);
pic_fgetbuf(pic, port, &buf, &len);
str = pic_str_value(pic, buf, len);
pic_fclose(pic, port);
return str;
for (p = fmt; *p; p++) {
if (*p == '%')
break;
}
str = pic_str_value(pic, fmt, p - fmt);
if (*p == 0) {
return str;
}
p++; /* skip '%' */
switch (*p++) {
case '\0':
return pic_str_value(pic, fmt, p - fmt - 1);
case 'd':
case 'i': {
int i = va_arg(ap, int);
str2 = pic_funcall(pic, "number->string", 1, pic_int_value(pic, i));
break;
}
case 'f': {
double f = va_arg(ap, double);
str2 = pic_funcall(pic, "number->string", 1, pic_float_value(pic, f));
break;
}
case 'c': {
char c = (char) va_arg(ap, int);
str2 = pic_str_value(pic, &c, 1);
break;
}
case 's': {
char *sval = va_arg(ap, char*);
str2 = pic_cstr_value(pic, sval);
break;
}
case 'p': {
static const char digits[] = "0123456789abcdef";
static const size_t bufsiz = sizeof(long) * CHAR_BIT / 4;
unsigned long vp = (unsigned long) va_arg(ap, void*);
char buf[2 + bufsiz + 1] = "0x", *p = buf + 2;
size_t i;
for (i = 0; i < bufsiz; ++i) {
p[bufsiz - i - 2] = digits[vp % 16];
vp /= 16;
}
p[i] = '\0';
str2 = pic_cstr_value(pic, buf);
break;
}
case '%':
str2 = pic_str_value(pic, &p[-1], 1);
break;
}
return pic_str_cat(pic, str, pic_str_cat(pic, str2, pic_vstrf_value(pic, p, ap)));
}
int