rewrite pic_get_args to check nparams first
This commit is contained in:
parent
40dc4a0e9c
commit
e2f10ba3ad
125
extlib/benz/vm.c
125
extlib/benz/vm.c
|
@ -58,50 +58,66 @@ 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, argc = pic->ci->argc;
|
int paramc, optc, ext = 0;
|
||||||
|
int i , argc = pic->ci->argc;
|
||||||
va_list ap;
|
va_list ap;
|
||||||
bool opt = false;
|
bool rest = false;
|
||||||
|
|
||||||
|
/* check nparams first */
|
||||||
|
for (paramc = 0; format[paramc]; paramc++) {
|
||||||
|
if (format[paramc] == '|') {
|
||||||
|
/* mark to skip '|' */
|
||||||
|
ext = 1;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
if (format[paramc] == '*') {
|
||||||
|
rest = true;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
for (optc = 0; rest || format[paramc + optc + ext]; optc++) {
|
||||||
|
if (format[paramc + optc + ext] == '*') {
|
||||||
|
rest = true;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* '|' should be followed by at least 1 char */
|
||||||
|
assert(ext <= optc);
|
||||||
|
/* '*' should not be followed by any char */
|
||||||
|
assert(format[paramc+optc+ext+rest] == '\0')
|
||||||
|
|
||||||
|
/* check argc */
|
||||||
|
if ((argc < paramc || paramc + optc < argc) && ! rest) {
|
||||||
|
pic_errorf(pic, "%s: wrong number of arguments (%d for %s%d)",
|
||||||
|
"procname", argc,
|
||||||
|
rest? "at least " : "",
|
||||||
|
paramc);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* start dispatching */
|
||||||
va_start(ap, format);
|
va_start(ap, format);
|
||||||
while ((c = *format++)) {
|
for(i = 1; i < min(argc, paramc+optc+ext) + 1; i++) {
|
||||||
switch (c) {
|
|
||||||
default:
|
|
||||||
if (argc <= i && ! opt) {
|
|
||||||
pic_errorf(pic, "wrong number of arguments");
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
case '|':
|
|
||||||
break;
|
|
||||||
case '*':
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* in order to run out of all arguments passed to this function
|
/* skip '|' if exists. This is always safe because of assert and argc check */
|
||||||
(i.e. do va_arg for each argument), optional argument existence
|
if ( i == paramc)
|
||||||
check is done in every case closure */
|
i += ext;
|
||||||
|
|
||||||
if (c == '*')
|
c = format[i];
|
||||||
break;
|
|
||||||
|
|
||||||
switch (c) {
|
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*);
|
||||||
if (i < argc) {
|
|
||||||
*p = GET_OPERAND(pic,i);
|
*p = GET_OPERAND(pic,i);
|
||||||
i++;
|
|
||||||
}
|
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case 'f': {
|
case 'f': {
|
||||||
double *f;
|
double *f;
|
||||||
|
|
||||||
f = va_arg(ap, double *);
|
f = va_arg(ap, double *);
|
||||||
if (i < argc) {
|
|
||||||
pic_value v;
|
pic_value v;
|
||||||
|
|
||||||
v = GET_OPERAND(pic, i);
|
v = GET_OPERAND(pic, i);
|
||||||
|
@ -115,8 +131,6 @@ pic_get_args(pic_state *pic, const char *format, ...)
|
||||||
default:
|
default:
|
||||||
pic_errorf(pic, "pic_get_args: expected float or int, but got ~s", v);
|
pic_errorf(pic, "pic_get_args: expected float or int, but got ~s", v);
|
||||||
}
|
}
|
||||||
i++;
|
|
||||||
}
|
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case 'F': {
|
case 'F': {
|
||||||
|
@ -125,7 +139,6 @@ pic_get_args(pic_state *pic, const char *format, ...)
|
||||||
|
|
||||||
f = va_arg(ap, double *);
|
f = va_arg(ap, double *);
|
||||||
e = va_arg(ap, bool *);
|
e = va_arg(ap, bool *);
|
||||||
if (i < argc) {
|
|
||||||
pic_value v;
|
pic_value v;
|
||||||
|
|
||||||
v = GET_OPERAND(pic, i);
|
v = GET_OPERAND(pic, i);
|
||||||
|
@ -141,8 +154,6 @@ pic_get_args(pic_state *pic, const char *format, ...)
|
||||||
default:
|
default:
|
||||||
pic_errorf(pic, "pic_get_args: expected float or int, but got ~s", v);
|
pic_errorf(pic, "pic_get_args: expected float or int, but got ~s", v);
|
||||||
}
|
}
|
||||||
i++;
|
|
||||||
}
|
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case 'I': {
|
case 'I': {
|
||||||
|
@ -151,7 +162,6 @@ pic_get_args(pic_state *pic, const char *format, ...)
|
||||||
|
|
||||||
k = va_arg(ap, int *);
|
k = va_arg(ap, int *);
|
||||||
e = va_arg(ap, bool *);
|
e = va_arg(ap, bool *);
|
||||||
if (i < argc) {
|
|
||||||
pic_value v;
|
pic_value v;
|
||||||
|
|
||||||
v = GET_OPERAND(pic, i);
|
v = GET_OPERAND(pic, i);
|
||||||
|
@ -167,15 +177,12 @@ pic_get_args(pic_state *pic, const char *format, ...)
|
||||||
default:
|
default:
|
||||||
pic_errorf(pic, "pic_get_args: expected float or int, but got ~s", v);
|
pic_errorf(pic, "pic_get_args: expected float or int, but got ~s", v);
|
||||||
}
|
}
|
||||||
i++;
|
|
||||||
}
|
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case 'i': {
|
case 'i': {
|
||||||
int *k;
|
int *k;
|
||||||
|
|
||||||
k = va_arg(ap, int *);
|
k = va_arg(ap, int *);
|
||||||
if (i < argc) {
|
|
||||||
pic_value v;
|
pic_value v;
|
||||||
|
|
||||||
v = GET_OPERAND(pic, i);
|
v = GET_OPERAND(pic, i);
|
||||||
|
@ -189,15 +196,12 @@ pic_get_args(pic_state *pic, const char *format, ...)
|
||||||
default:
|
default:
|
||||||
pic_errorf(pic, "pic_get_args: expected int, but got ~s", v);
|
pic_errorf(pic, "pic_get_args: expected int, but got ~s", v);
|
||||||
}
|
}
|
||||||
i++;
|
|
||||||
}
|
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case 'k': {
|
case 'k': {
|
||||||
size_t *k;
|
size_t *k;
|
||||||
|
|
||||||
k = va_arg(ap, size_t *);
|
k = va_arg(ap, size_t *);
|
||||||
if (i < argc) {
|
|
||||||
pic_value v;
|
pic_value v;
|
||||||
int x;
|
int x;
|
||||||
|
|
||||||
|
@ -218,8 +222,6 @@ pic_get_args(pic_state *pic, const char *format, ...)
|
||||||
default:
|
default:
|
||||||
pic_errorf(pic, "pic_get_args: expected int, but got ~s", v);
|
pic_errorf(pic, "pic_get_args: expected int, but got ~s", v);
|
||||||
}
|
}
|
||||||
i++;
|
|
||||||
}
|
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case 's': {
|
case 's': {
|
||||||
|
@ -227,7 +229,6 @@ pic_get_args(pic_state *pic, const char *format, ...)
|
||||||
pic_value v;
|
pic_value v;
|
||||||
|
|
||||||
str = va_arg(ap, pic_str **);
|
str = va_arg(ap, pic_str **);
|
||||||
if (i < argc) {
|
|
||||||
v = GET_OPERAND(pic,i);
|
v = GET_OPERAND(pic,i);
|
||||||
if (pic_str_p(v)) {
|
if (pic_str_p(v)) {
|
||||||
*str = pic_str_ptr(v);
|
*str = pic_str_ptr(v);
|
||||||
|
@ -235,8 +236,6 @@ pic_get_args(pic_state *pic, const char *format, ...)
|
||||||
else {
|
else {
|
||||||
pic_errorf(pic, "pic_get_args: expected string, but got ~s", v);
|
pic_errorf(pic, "pic_get_args: expected string, but got ~s", v);
|
||||||
}
|
}
|
||||||
i++;
|
|
||||||
}
|
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case 'z': {
|
case 'z': {
|
||||||
|
@ -244,14 +243,11 @@ pic_get_args(pic_state *pic, const char *format, ...)
|
||||||
pic_value v;
|
pic_value v;
|
||||||
|
|
||||||
cstr = va_arg(ap, const char **);
|
cstr = va_arg(ap, const char **);
|
||||||
if (i < argc) {
|
|
||||||
v = GET_OPERAND(pic,i);
|
v = GET_OPERAND(pic,i);
|
||||||
if (! pic_str_p(v)) {
|
if (! pic_str_p(v)) {
|
||||||
pic_errorf(pic, "pic_get_args: expected string, but got ~s", v);
|
pic_errorf(pic, "pic_get_args: expected string, but got ~s", v);
|
||||||
}
|
}
|
||||||
*cstr = pic_str_cstr(pic_str_ptr(v));
|
*cstr = pic_str_cstr(pic_str_ptr(v));
|
||||||
i++;
|
|
||||||
}
|
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case 'm': {
|
case 'm': {
|
||||||
|
@ -259,7 +255,6 @@ pic_get_args(pic_state *pic, const char *format, ...)
|
||||||
pic_value v;
|
pic_value v;
|
||||||
|
|
||||||
m = va_arg(ap, pic_sym **);
|
m = va_arg(ap, pic_sym **);
|
||||||
if (i < argc) {
|
|
||||||
v = GET_OPERAND(pic,i);
|
v = GET_OPERAND(pic,i);
|
||||||
if (pic_sym_p(v)) {
|
if (pic_sym_p(v)) {
|
||||||
*m = pic_sym_ptr(v);
|
*m = pic_sym_ptr(v);
|
||||||
|
@ -267,8 +262,6 @@ pic_get_args(pic_state *pic, const char *format, ...)
|
||||||
else {
|
else {
|
||||||
pic_errorf(pic, "pic_get_args: expected symbol, but got ~s", v);
|
pic_errorf(pic, "pic_get_args: expected symbol, but got ~s", v);
|
||||||
}
|
}
|
||||||
i++;
|
|
||||||
}
|
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case 'v': {
|
case 'v': {
|
||||||
|
@ -276,7 +269,6 @@ pic_get_args(pic_state *pic, const char *format, ...)
|
||||||
pic_value v;
|
pic_value v;
|
||||||
|
|
||||||
vec = va_arg(ap, struct pic_vector **);
|
vec = va_arg(ap, struct pic_vector **);
|
||||||
if (i < argc) {
|
|
||||||
v = GET_OPERAND(pic,i);
|
v = GET_OPERAND(pic,i);
|
||||||
if (pic_vec_p(v)) {
|
if (pic_vec_p(v)) {
|
||||||
*vec = pic_vec_ptr(v);
|
*vec = pic_vec_ptr(v);
|
||||||
|
@ -284,8 +276,6 @@ pic_get_args(pic_state *pic, const char *format, ...)
|
||||||
else {
|
else {
|
||||||
pic_errorf(pic, "pic_get_args: expected vector, but got ~s", v);
|
pic_errorf(pic, "pic_get_args: expected vector, but got ~s", v);
|
||||||
}
|
}
|
||||||
i++;
|
|
||||||
}
|
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case 'b': {
|
case 'b': {
|
||||||
|
@ -293,7 +283,6 @@ pic_get_args(pic_state *pic, const char *format, ...)
|
||||||
pic_value v;
|
pic_value v;
|
||||||
|
|
||||||
b = va_arg(ap, struct pic_blob **);
|
b = va_arg(ap, struct pic_blob **);
|
||||||
if (i < argc) {
|
|
||||||
v = GET_OPERAND(pic,i);
|
v = GET_OPERAND(pic,i);
|
||||||
if (pic_blob_p(v)) {
|
if (pic_blob_p(v)) {
|
||||||
*b = pic_blob_ptr(v);
|
*b = pic_blob_ptr(v);
|
||||||
|
@ -301,8 +290,6 @@ pic_get_args(pic_state *pic, const char *format, ...)
|
||||||
else {
|
else {
|
||||||
pic_errorf(pic, "pic_get_args: expected bytevector, but got ~s", v);
|
pic_errorf(pic, "pic_get_args: expected bytevector, but got ~s", v);
|
||||||
}
|
}
|
||||||
i++;
|
|
||||||
}
|
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case 'c': {
|
case 'c': {
|
||||||
|
@ -310,7 +297,6 @@ pic_get_args(pic_state *pic, const char *format, ...)
|
||||||
pic_value v;
|
pic_value v;
|
||||||
|
|
||||||
k = va_arg(ap, char *);
|
k = va_arg(ap, char *);
|
||||||
if (i < argc) {
|
|
||||||
v = GET_OPERAND(pic,i);
|
v = GET_OPERAND(pic,i);
|
||||||
if (pic_char_p(v)) {
|
if (pic_char_p(v)) {
|
||||||
*k = pic_char(v);
|
*k = pic_char(v);
|
||||||
|
@ -318,8 +304,6 @@ pic_get_args(pic_state *pic, const char *format, ...)
|
||||||
else {
|
else {
|
||||||
pic_errorf(pic, "pic_get_args: expected char, but got ~s", v);
|
pic_errorf(pic, "pic_get_args: expected char, but got ~s", v);
|
||||||
}
|
}
|
||||||
i++;
|
|
||||||
}
|
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case 'l': {
|
case 'l': {
|
||||||
|
@ -327,7 +311,6 @@ pic_get_args(pic_state *pic, const char *format, ...)
|
||||||
pic_value v;
|
pic_value v;
|
||||||
|
|
||||||
l = va_arg(ap, struct pic_proc **);
|
l = va_arg(ap, struct pic_proc **);
|
||||||
if (i < argc) {
|
|
||||||
v = GET_OPERAND(pic,i);
|
v = GET_OPERAND(pic,i);
|
||||||
if (pic_proc_p(v)) {
|
if (pic_proc_p(v)) {
|
||||||
*l = pic_proc_ptr(v);
|
*l = pic_proc_ptr(v);
|
||||||
|
@ -335,8 +318,6 @@ pic_get_args(pic_state *pic, const char *format, ...)
|
||||||
else {
|
else {
|
||||||
pic_errorf(pic, "pic_get_args, expected procedure, but got ~s", v);
|
pic_errorf(pic, "pic_get_args, expected procedure, but got ~s", v);
|
||||||
}
|
}
|
||||||
i++;
|
|
||||||
}
|
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case 'p': {
|
case 'p': {
|
||||||
|
@ -344,7 +325,6 @@ pic_get_args(pic_state *pic, const char *format, ...)
|
||||||
pic_value v;
|
pic_value v;
|
||||||
|
|
||||||
p = va_arg(ap, struct pic_port **);
|
p = va_arg(ap, struct pic_port **);
|
||||||
if (i < argc) {
|
|
||||||
v = GET_OPERAND(pic,i);
|
v = GET_OPERAND(pic,i);
|
||||||
if (pic_port_p(v)) {
|
if (pic_port_p(v)) {
|
||||||
*p = pic_port_ptr(v);
|
*p = pic_port_ptr(v);
|
||||||
|
@ -352,8 +332,6 @@ pic_get_args(pic_state *pic, const char *format, ...)
|
||||||
else {
|
else {
|
||||||
pic_errorf(pic, "pic_get_args, expected port, but got ~s", v);
|
pic_errorf(pic, "pic_get_args, expected port, but got ~s", v);
|
||||||
}
|
}
|
||||||
i++;
|
|
||||||
}
|
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case 'd': {
|
case 'd': {
|
||||||
|
@ -361,7 +339,6 @@ pic_get_args(pic_state *pic, const char *format, ...)
|
||||||
pic_value v;
|
pic_value v;
|
||||||
|
|
||||||
d = va_arg(ap, struct pic_dict **);
|
d = va_arg(ap, struct pic_dict **);
|
||||||
if (i < argc) {
|
|
||||||
v = GET_OPERAND(pic,i);
|
v = GET_OPERAND(pic,i);
|
||||||
if (pic_dict_p(v)) {
|
if (pic_dict_p(v)) {
|
||||||
*d = pic_dict_ptr(v);
|
*d = pic_dict_ptr(v);
|
||||||
|
@ -369,8 +346,6 @@ pic_get_args(pic_state *pic, const char *format, ...)
|
||||||
else {
|
else {
|
||||||
pic_errorf(pic, "pic_get_args, expected dictionary, but got ~s", v);
|
pic_errorf(pic, "pic_get_args, expected dictionary, but got ~s", v);
|
||||||
}
|
}
|
||||||
i++;
|
|
||||||
}
|
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case 'r': {
|
case 'r': {
|
||||||
|
@ -378,7 +353,6 @@ pic_get_args(pic_state *pic, const char *format, ...)
|
||||||
pic_value v;
|
pic_value v;
|
||||||
|
|
||||||
r = va_arg(ap, struct pic_record **);
|
r = va_arg(ap, struct pic_record **);
|
||||||
if (i < argc) {
|
|
||||||
v = GET_OPERAND(pic,i);
|
v = GET_OPERAND(pic,i);
|
||||||
if (pic_record_p(v)) {
|
if (pic_record_p(v)) {
|
||||||
*r = pic_record_ptr(v);
|
*r = pic_record_ptr(v);
|
||||||
|
@ -386,8 +360,6 @@ pic_get_args(pic_state *pic, const char *format, ...)
|
||||||
else {
|
else {
|
||||||
pic_errorf(pic, "pic_get_args: expected record, but got ~s", v);
|
pic_errorf(pic, "pic_get_args: expected record, but got ~s", v);
|
||||||
}
|
}
|
||||||
i++;
|
|
||||||
}
|
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case 'e': {
|
case 'e': {
|
||||||
|
@ -395,7 +367,6 @@ pic_get_args(pic_state *pic, const char *format, ...)
|
||||||
pic_value v;
|
pic_value v;
|
||||||
|
|
||||||
e = va_arg(ap, struct pic_error **);
|
e = va_arg(ap, struct pic_error **);
|
||||||
if (i < argc) {
|
|
||||||
v = GET_OPERAND(pic,i);
|
v = GET_OPERAND(pic,i);
|
||||||
if (pic_error_p(v)) {
|
if (pic_error_p(v)) {
|
||||||
*e = pic_error_ptr(v);
|
*e = pic_error_ptr(v);
|
||||||
|
@ -403,31 +374,25 @@ pic_get_args(pic_state *pic, const char *format, ...)
|
||||||
else {
|
else {
|
||||||
pic_errorf(pic, "pic_get_args, expected error");
|
pic_errorf(pic, "pic_get_args, expected error");
|
||||||
}
|
}
|
||||||
i++;
|
|
||||||
}
|
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
default:
|
default:
|
||||||
pic_errorf(pic, "pic_get_args: invalid argument specifier '%c' given", c);
|
pic_errorf(pic, "pic_get_args: invalid argument specifier '%c' given", c);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if ('*' == c) {
|
if ( rest ) {
|
||||||
size_t *n;
|
size_t *n;
|
||||||
pic_value **argv;
|
pic_value **argv;
|
||||||
|
|
||||||
n = va_arg(ap, size_t *);
|
n = va_arg(ap, size_t *);
|
||||||
argv = va_arg(ap, pic_value **);
|
argv = va_arg(ap, pic_value **);
|
||||||
if (i <= argc) {
|
if (i <= argc) {
|
||||||
*n = (size_t)(argc - i);
|
*n = (size_t)(argc - (paramc + optc));
|
||||||
*argv = &GET_OPERAND(pic, i);
|
*argv = &GET_OPERAND(pic, i);
|
||||||
i = argc;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else if (argc > i) {
|
|
||||||
pic_errorf(pic, "wrong number of arguments");
|
|
||||||
}
|
|
||||||
va_end(ap);
|
va_end(ap);
|
||||||
return i - 1;
|
return argc - 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
|
|
Loading…
Reference in New Issue