reimplement pic_strf_value
This commit is contained in:
parent
aa4f94e378
commit
cbec7646c0
|
@ -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);
|
||||
}
|
||||
|
|
|
@ -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");
|
||||
|
|
|
@ -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 */
|
||||
|
||||
|
||||
/*
|
||||
|
|
13
lib/object.h
13
lib/object.h
|
@ -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 {
|
||||
|
|
107
lib/port.c
107
lib/port.c
|
@ -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
|
||||
|
|
65
lib/string.c
65
lib/string.c
|
@ -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
|
||||
|
|
Loading…
Reference in New Issue