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");
|
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_value
|
||||||
pic_file_exists_p(pic_state *pic)
|
pic_file_exists_p(pic_state *pic)
|
||||||
{
|
{
|
||||||
|
@ -154,13 +182,21 @@ pic_file_delete(pic_state *pic)
|
||||||
void
|
void
|
||||||
pic_init_file(pic_state *pic)
|
pic_init_file(pic_state *pic)
|
||||||
{
|
{
|
||||||
pic_defvar(pic, "current-input-port", pic_fopen(pic, stdin, "r"));
|
pic_value i, o, e;
|
||||||
pic_defvar(pic, "current-output-port", pic_fopen(pic, stdout, "w"));
|
|
||||||
pic_defvar(pic, "current-error-port", pic_fopen(pic, stdout, "w"));
|
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-input-file", pic_file_open_input_file);
|
||||||
pic_defun(pic, "open-output-file", pic_file_open_output_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-input-file", pic_file_open_binary_input_file);
|
||||||
pic_defun(pic, "open-binary-output-file", pic_file_open_output_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, "file-exists?", pic_file_exists_p);
|
||||||
pic_defun(pic, "delete-file", pic_file_delete);
|
pic_defun(pic, "delete-file", pic_file_delete);
|
||||||
}
|
}
|
||||||
|
|
|
@ -17,10 +17,12 @@ main(int argc, char *argv[])
|
||||||
if (argc == 1) { /* repl */
|
if (argc == 1) { /* repl */
|
||||||
while (1) {
|
while (1) {
|
||||||
pic_printf(pic, "> ");
|
pic_printf(pic, "> ");
|
||||||
|
pic_fflush(pic, pic_stdout(pic));
|
||||||
e = pic_funcall(pic, "read", 0);
|
e = pic_funcall(pic, "read", 0);
|
||||||
if (pic_eof_p(pic, e))
|
if (pic_eof_p(pic, e))
|
||||||
break;
|
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 */
|
} else if (argc == 2) { /* load file */
|
||||||
FILE *file = fopen(argv[1], "r");
|
FILE *file = fopen(argv[1], "r");
|
||||||
|
|
|
@ -258,6 +258,10 @@ typedef struct {
|
||||||
#define PIC_SEEK_END 1
|
#define PIC_SEEK_END 1
|
||||||
#define PIC_SEEK_SET 2
|
#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_stdin(pic) pic_funcall(pic, "current-input-port", 0)
|
||||||
#define pic_stdout(pic) pic_funcall(pic, "current-output-port", 0)
|
#define pic_stdout(pic) pic_funcall(pic, "current-output-port", 0)
|
||||||
#define pic_stderr(pic) pic_funcall(pic, "current-error-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);
|
char *pic_fgets(pic_state *, char *s, int size, pic_value port);
|
||||||
int pic_ungetc(pic_state *, int c, pic_value port);
|
int pic_ungetc(pic_state *, int c, pic_value port);
|
||||||
int pic_fflush(pic_state *, 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 */
|
/* formatted output */
|
||||||
int pic_printf(pic_state *, const char *fmt, ...);
|
int pic_printf(pic_state *, const char *fmt, ...);
|
||||||
int pic_fprintf(pic_state *, pic_value port, 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);
|
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 {
|
enum {
|
||||||
FILE_READ = 01,
|
FILE_READ = 01,
|
||||||
FILE_WRITE = 02,
|
FILE_WRITE = 02,
|
||||||
FILE_UNBUF = 04,
|
FILE_UNBUF = 04,
|
||||||
FILE_EOF = 010,
|
FILE_EOF = 010,
|
||||||
FILE_ERR = 020,
|
FILE_ERR = 020,
|
||||||
FILE_LNBUF = 040
|
FILE_LNBUF = 040,
|
||||||
|
FILE_SETBUF = 0100
|
||||||
};
|
};
|
||||||
|
|
||||||
struct port {
|
struct port {
|
||||||
|
|
107
lib/port.c
107
lib/port.c
|
@ -35,13 +35,13 @@ pic_fclose(pic_state *pic, pic_value port)
|
||||||
return 0;
|
return 0;
|
||||||
pic_fflush(pic, port);
|
pic_fflush(pic, port);
|
||||||
fp->flag = 0;
|
fp->flag = 0;
|
||||||
if (fp->base != fp->buf)
|
if (fp->base != fp->buf && (fp->flag & FILE_SETBUF) == 0)
|
||||||
pic_free(pic, fp->base);
|
pic_free(pic, fp->base);
|
||||||
return fp->vtable->close(pic, fp->cookie);
|
return fp->vtable->close(pic, fp->cookie);
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
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;
|
struct file *fp = &port_ptr(pic, port)->file;
|
||||||
|
|
||||||
|
@ -49,7 +49,7 @@ pic_clearerr(pic_state *PIC_UNUSED(pic), pic_value port)
|
||||||
}
|
}
|
||||||
|
|
||||||
int
|
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;
|
struct file *fp = &port_ptr(pic, port)->file;
|
||||||
|
|
||||||
|
@ -57,13 +57,36 @@ pic_feof(pic_state *PIC_UNUSED(pic), pic_value port)
|
||||||
}
|
}
|
||||||
|
|
||||||
int
|
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;
|
struct file *fp = &port_ptr(pic, port)->file;
|
||||||
|
|
||||||
return (fp->flag & FILE_ERR) != 0;
|
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
|
static int
|
||||||
fillbuf(pic_state *pic, struct file *fp)
|
fillbuf(pic_state *pic, struct file *fp)
|
||||||
{
|
{
|
||||||
|
@ -230,7 +253,7 @@ pic_fgets(pic_state *pic, char *s, int size, pic_value port)
|
||||||
}
|
}
|
||||||
|
|
||||||
int
|
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;
|
struct file *fp = &port_ptr(pic, port)->file;
|
||||||
unsigned char uc = c;
|
unsigned char uc = c;
|
||||||
|
@ -311,79 +334,7 @@ pic_fseek(pic_state *pic, pic_value port, long offset, int whence)
|
||||||
int
|
int
|
||||||
pic_vfprintf(pic_state *pic, pic_value port, const char *fmt, va_list ap)
|
pic_vfprintf(pic_state *pic, pic_value port, const char *fmt, va_list ap)
|
||||||
{
|
{
|
||||||
const char *p;
|
return pic_fputs(pic, pic_cstr(pic, pic_vstrf_value(pic, fmt, ap), NULL), port);
|
||||||
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;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
int
|
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);
|
va_start(ap, fmt);
|
||||||
str = pic_vstrf_value(pic, fmt, ap);
|
str = pic_vstrf_value(pic, fmt, ap);
|
||||||
va_end(ap);
|
va_end(ap);
|
||||||
|
|
||||||
return str;
|
return str;
|
||||||
}
|
}
|
||||||
|
|
||||||
pic_value
|
pic_value
|
||||||
pic_vstrf_value(pic_state *pic, const char *fmt, va_list ap)
|
pic_vstrf_value(pic_state *pic, const char *fmt, va_list ap)
|
||||||
{
|
{
|
||||||
pic_value str, port;
|
pic_value str, str2;
|
||||||
const char *buf;
|
const char *p;
|
||||||
int len;
|
|
||||||
|
|
||||||
port = pic_fmemopen(pic, NULL, 0, "w");
|
for (p = fmt; *p; p++) {
|
||||||
|
if (*p == '%')
|
||||||
pic_vfprintf(pic, port, fmt, ap);
|
break;
|
||||||
pic_fgetbuf(pic, port, &buf, &len);
|
}
|
||||||
str = pic_str_value(pic, buf, len);
|
str = pic_str_value(pic, fmt, p - fmt);
|
||||||
pic_fclose(pic, port);
|
if (*p == 0) {
|
||||||
return str;
|
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
|
int
|
||||||
|
|
Loading…
Reference in New Issue