python 1.0.2 (getargs)

Donald Beaudry (don@vicorp.com)
Thu, 5 May 94 10:56:18 EDT

I just grabed 1.0.2 and was quite pleased with all of the new
features. Still, I would like to see some sort of optional white
space stripping on multi-line strings, but the current implemention is
sufficient for my needs.

I tried running some of my code that uses the "O!" option of getargs
and was supprised to find that it did not work. A quick look at the
code revealed the problem. (belive me it is obvious)

While comparing my version to yours I was reminded of a couple of new
options that I had added: "O&" and "O?". The "O?" option lets you
pass an inquiry function pointer along with the pointer to the object
pointer. The argument is only assigned to the object pointer if the
inquiry function returns a non zero value when called with the
argument as its only parameter. The "O&" option allows you to pass a
conversion function along with the address of a place to store the
resulting conversion. So given the function:

int convert_int(object *io, void *ia)
{
*(long)ia = getintvalue(io);
return 1;
}

you could say:

getargs(args, "O&", convert_int, &my_int)

instead of the much simpler:

getargs(args, "i", &my_int)

Now, this gets really useful when you need to do somthing like this
more than once:

struct {
int argc;
char **argv;
} argv_argc;

getargs(args, "O&", convert_argv_argc, &argv_argc)

The conversion routine is left as an exercise for the reader.

I suppose that given "O&" there is really no need for "O?", but I came
up with the "O?" option first. Also, there seems to be a conceptual
difference so I find the distinction useful.

>From Python/modsupport.c, the offending code:

case 'O': /* object */ {
typeobject *type = NULL;
object **p;
if (*format == '!') {
type = va_arg(*p_va, typeobject *);
format++;
}
p = va_arg(*p_va, object **);
if (type && (*p)->ob_type != type) {
char buf[200];
sprintf(buf, "Object of type %.100s expected",
type->tp_name);
err_setstr(TypeError, buf);
return 0;
}
*p = arg;
break;
}

The enhancement (minus the fancy error message):

case 'O': /* object */ {
typeobject *type;
object **p;
if (*format == '!') {
format++;
type = va_arg(*p_va, typeobject*);
if (arg->ob_type != type)
return 0;
else {
p = va_arg(*p_va, object **);
*p = arg;
}
}
else if (*format == '?') {
inquiry pred = va_arg(*p_va, inquiry);
format++;
if ((*pred)(arg)) {
p = va_arg(*p_va, object **);
*p = arg;
}
}
else if (*format == '&') {
convertfunc convert = va_arg(*p_va, convertfunc);
void *addr = va_arg(*p_va, void *);
format++;
if (! (*convert)(arg, addr))
return 0;
}
else {
p = va_arg(*p_va, object **);
*p = arg;
}
break;
}

Given your convention that uppercase options return objects and
lowcase options return C types, you might want to change "O&" to
"o&". Call it what you like, its the functionality I'm after.

--Don

______ ______
\_\_\_\ /#/#/#/
\_\_\_\ ______
\_\_\_V#/#/#/ Donald Beaudry don@vicorp.com
\_\_/#/#/#/ V. I. Corporation uunet!vicorp!don
\_/#/#/#/ 47 Pleasant Street PHONE: (413) 586-4144
V#/#/#/ Northampton, MA 01060 FAX: (413) 586-3805