rewrite to be clean
This commit is contained in:
parent
9571030f7e
commit
1700610729
|
@ -58,38 +58,43 @@ int
|
||||||
pic_get_args(pic_state *pic, const char *format, ...)
|
pic_get_args(pic_state *pic, const char *format, ...)
|
||||||
{
|
{
|
||||||
char c;
|
char c;
|
||||||
int paramc, optc, ext = 0;
|
int paramc, optc, min;
|
||||||
int i , argc = pic->ci->argc;
|
int i , argc = pic->ci->argc - 1;
|
||||||
va_list ap;
|
va_list ap;
|
||||||
bool rest = false;
|
bool rest = false, opt = false;
|
||||||
|
|
||||||
|
/* paramc: required args count as scheme proc
|
||||||
|
optc: optional args count as scheme proc
|
||||||
|
argc: passed args count as scheme proc
|
||||||
|
vargc: args count passed to this function
|
||||||
|
*/
|
||||||
|
|
||||||
/* check nparams first */
|
/* check nparams first */
|
||||||
for (paramc = 0; format[paramc]; paramc++) {
|
for (paramc = 0, c = *format; c; c = format[++paramc]) {
|
||||||
if (format[paramc] == '|') {
|
if (c == '|') {
|
||||||
/* mark to skip '|' */
|
opt = true;
|
||||||
ext = 1;
|
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
if (format[paramc] == '*') {
|
else if (c == '*') {
|
||||||
rest = true;
|
rest = true;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
for (optc = 0; rest || format[paramc + optc + ext]; optc++) {
|
for (optc = 0; opt && c; c = format[paramc + opt + ++optc]) {
|
||||||
if (format[paramc + optc + ext] == '*') {
|
if (c == '*') {
|
||||||
rest = true;
|
rest = true;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/* '|' should be followed by at least 1 char */
|
/* '|' should be followed by at least 1 char */
|
||||||
assert(ext <= optc);
|
assert(opt <= optc);
|
||||||
/* '*' should not be followed by any char */
|
/* '*' should not be followed by any char */
|
||||||
assert(format[paramc+optc+ext+rest] == '\0')
|
assert(format[paramc + opt + optc + rest] == '\0');
|
||||||
|
|
||||||
/* check argc */
|
/* check argc. */
|
||||||
if ((argc < paramc || paramc + optc < argc) && ! rest) {
|
if (argc < paramc || (paramc + optc < argc && ! rest)) {
|
||||||
pic_errorf(pic, "%s: wrong number of arguments (%d for %s%d)",
|
pic_errorf(pic, "%s: wrong number of arguments (%d for %s%d)",
|
||||||
"procname", argc,
|
"procname", argc,
|
||||||
rest? "at least " : "",
|
rest? "at least " : "",
|
||||||
|
@ -98,13 +103,12 @@ pic_get_args(pic_state *pic, const char *format, ...)
|
||||||
|
|
||||||
/* start dispatching */
|
/* start dispatching */
|
||||||
va_start(ap, format);
|
va_start(ap, format);
|
||||||
for(i = 1; i < min(argc, paramc+optc+ext) + 1; i++) {
|
min = paramc + optc + rest < argc ? paramc + optc + rest : argc;
|
||||||
|
for(i = 1; i < min + 1; i++) {
|
||||||
|
|
||||||
|
c = *format++;
|
||||||
/* skip '|' if exists. This is always safe because of assert and argc check */
|
/* skip '|' if exists. This is always safe because of assert and argc check */
|
||||||
if ( i == paramc)
|
c = c == '|' ? *format++ : c;
|
||||||
i += ext;
|
|
||||||
|
|
||||||
c = format[i];
|
|
||||||
|
|
||||||
switch (c) {
|
switch (c) {
|
||||||
case 'o': {
|
case 'o': {
|
||||||
|
@ -378,23 +382,24 @@ pic_get_args(pic_state *pic, const char *format, ...)
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
case '*': {
|
||||||
|
size_t *n;
|
||||||
|
pic_value **argv;
|
||||||
|
|
||||||
|
n = va_arg(ap, size_t *);
|
||||||
|
argv = va_arg(ap, pic_value **);
|
||||||
|
if ( paramc + optc < argc) {
|
||||||
|
*n = (size_t)(argc - (paramc + optc));
|
||||||
|
*argv = &GET_OPERAND(pic, i);
|
||||||
|
}
|
||||||
|
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 ( rest ) {
|
|
||||||
size_t *n;
|
|
||||||
pic_value **argv;
|
|
||||||
|
|
||||||
n = va_arg(ap, size_t *);
|
|
||||||
argv = va_arg(ap, pic_value **);
|
|
||||||
if (i <= argc) {
|
|
||||||
*n = (size_t)(argc - (paramc + optc));
|
|
||||||
*argv = &GET_OPERAND(pic, i);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
va_end(ap);
|
va_end(ap);
|
||||||
return argc - 1;
|
return argc;
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
|
|
Loading…
Reference in New Issue