pic_get_args supports optional argument

This commit is contained in:
Yuichi Nishiwaki 2013-10-21 13:57:02 +09:00
parent 6c8dd50ab8
commit 86177b7c4e
3 changed files with 29 additions and 7 deletions

View File

@ -62,7 +62,7 @@ void pic_gc_arena_restore(pic_state *, int);
pic_state *pic_open(int argc, char *argv[], char **envp); pic_state *pic_open(int argc, char *argv[], char **envp);
void pic_close(pic_state *); void pic_close(pic_state *);
void pic_get_args(pic_state *, const char *, ...); int pic_get_args(pic_state *, const char *, ...);
void pic_defun(pic_state *, const char *, pic_func_t); void pic_defun(pic_state *, const char *, pic_func_t);
bool pic_eq_p(pic_state *, pic_value, pic_value); bool pic_eq_p(pic_state *, pic_value, pic_value);

View File

@ -110,4 +110,3 @@ pic_init_port(pic_state *pic)
pic_defun(pic, "write", pic_port_write); pic_defun(pic, "write", pic_port_write);
pic_defun(pic, "newline", pic_port_newline); pic_defun(pic, "newline", pic_port_newline);
} }

View File

@ -7,22 +7,38 @@
#include "picrin/irep.h" #include "picrin/irep.h"
#include "picrin/string.h" #include "picrin/string.h"
void #define GET_OPERAND(pic,n) ((pic)->sp[-1-(n)])
int
pic_get_args(pic_state *pic, const char *format, ...) pic_get_args(pic_state *pic, const char *format, ...)
{ {
char c; char c;
int i = -1; int i = 0, argc = pic->ci->argc - 1;
va_list ap; va_list ap;
bool opt = false;
va_start(ap, format); va_start(ap, format);
while ((c = *format++)) { while ((c = *format++)) {
switch (c) { switch (c) {
default:
if (argc <= i && ! opt) {
pic_error(pic, "wrong number of arguments");
}
break;
case '|':
break;
}
switch (c) {
case '|':
opt = true;
break;
case 'o': case 'o':
{ {
pic_value *p; pic_value *p;
p = va_arg(ap, pic_value*); p = va_arg(ap, pic_value*);
*p = pic->sp[i--]; *p = GET_OPERAND(pic,i);
i++;
} }
break; break;
case 'f': case 'f':
@ -30,7 +46,8 @@ pic_get_args(pic_state *pic, const char *format, ...)
double *f; double *f;
f = va_arg(ap, double *); f = va_arg(ap, double *);
*f = pic_float(pic->sp[i--]); *f = pic_float(GET_OPERAND(pic,i));
i++;
} }
break; break;
case 's': case 's':
@ -41,13 +58,19 @@ pic_get_args(pic_state *pic, const char *format, ...)
cstr = va_arg(ap, char **); cstr = va_arg(ap, char **);
len = va_arg(ap, size_t *); len = va_arg(ap, size_t *);
str = pic->sp[i--]; str = GET_OPERAND(pic,i);
*cstr = pic_str_ptr(str)->str; *cstr = pic_str_ptr(str)->str;
*len = pic_str_ptr(str)->len; *len = pic_str_ptr(str)->len;
i++;
} }
break; break;
} }
} }
if (argc > i) {
pic_error(pic, "wrong number of arguments");
}
va_end(ap);
return i;
} }
#if PIC_DIRECT_THREADED_VM #if PIC_DIRECT_THREADED_VM