Format strings for getargs()

The getargs() function is declared in `modsupport.h' as follows:

    int getargs(object *arg, char *format, ...);

The remaining arguments must be addresses of variables whose type is determined by the format string. For the conversion to succeed, the arg object must match the format and the format must be exhausted. Note that while getargs() checks that the Python object really is of the specified type, it cannot check the validity of the addresses of C variables provided in the call: if you make mistakes there, your code will probably dump core.

A non-empty format string consists of a single `format unit'. A format unit describes one Python object; it is usually a single character or a parenthesized sequence of format units. The type of a format units is determined from its first character, the `format letter':

`s' (string)
The Python object must be a string object. The C argument must be a (char**) (i.e. the address of a character pointer), and a pointer to the C string contained in the Python object is stored into it. You must not provide storage to store the string; a pointer to an existing string is stored into the character pointer variable whose address you pass. If the next character in the format string is `#', another C argument of type (int*) must be present, and the length of the Python string (not counting the trailing zero byte) is stored into it.

`z' (string or zero, i.e. NULL)
Like `s', but the object may also be None. In this case the string pointer is set to NULL and if a `#' is present the size is set to 0.

`b' (byte, i.e. char interpreted as tiny int)
The object must be a Python integer. The C argument must be a (char*).

`h' (half, i.e. short)
The object must be a Python integer. The C argument must be a (short*).

`i' (int)
The object must be a Python integer. The C argument must be an (int*).

`l' (long)
The object must be a (plain!) Python integer. The C argument must be a (long*).

`c' (char)
The Python object must be a string of length 1. The C argument must be a (char*). (Don't pass an (int*)!)

`f' (float)
The object must be a Python int or float. The C argument must be a (float*).

`d' (double)
The object must be a Python int or float. The C argument must be a (double*).

`S' (string object)
The object must be a Python string. The C argument must be an (object**) (i.e. the address of an object pointer). The C program thus gets back the actual string object that was passed, not just a pointer to its array of characters and its size as for format character `s'. The reference count of the object has not been increased.

`O' (object)
The object can be any Python object, including None, but not NULL. The C argument must be an (object**). This can be used if an argument list must contain objects of a type for which no format letter exist: the caller must then check that it has the right type. The reference count of the object has not been increased.

`(' (tuple)
The object must be a Python tuple. Following the `(' character in the format string must come a number of format units describing the elements of the tuple, followed by a `)' character. Tuple format units may be nested. (There are no exceptions for empty and singleton tuples; `()' specifies an empty tuple and `(i)' a singleton of one integer. Normally you don't want to use the latter, since it is hard for the Python user to specify.

More format characters will probably be added as the need arises. It should (but currently isn't) be allowed to use Python long integers whereever integers are expected, and perform a range check. (A range check is in fact always necessary for the `b', `h' and `i' format letters, but this is currently not implemented.)

Some example calls:

    int ok;
    int i, j;
    long k, l;
    char *s;
    int size;

    ok = getargs(args, ""); /* No arguments */
        /* Python call: f() */
    
    ok = getargs(args, "s", &s); /* A string */
        /* Possible Python call: f('whoops!') */

    ok = getargs(args, "(lls)", &k, &l, &s); /* Two longs and a string */
        /* Possible Python call: f(1, 2, 'three') */
    
    ok = getargs(args, "((ii)s#)", &i, &j, &s, &size);
        /* A pair of ints and a string, whose size is also returned */
        /* Possible Python call: f(1, 2, 'three') */

    {
        int left, top, right, bottom, h, v;
        ok = getargs(args, "(((ii)(ii))(ii))",
                 &left, &top, &right, &bottom, &h, &v);
                 /* A rectangle and a point */
                 /* Possible Python call:
                    f( ((0, 0), (400, 300)), (10, 10)) */
    }

Note that the `top level' of a non-empty format string must consist of a single unit; strings like `is' and `(ii)s#' are not valid format strings. (But `s#' is.) If you have multiple arguments, the format must therefore always be enclosed in parentheses, as in the examples `((ii)s#)' and `(((ii)(ii))(ii)'. (The current implementation does not complain when more than one unparenthesized format unit is given. Sorry.)

The getargs() function does not support variable-length argument lists. In simple cases you can fake these by trying several calls to getargs() until one succeeds, but you must take care to call err_clear() before each retry. For example:

    static object *my_method(self, args) object *self, *args; {
        int i, j, k;

        if (getargs(args, "(ii)", &i, &j)) {
            k = 0; /* Use default third argument */
        }
        else {
            err_clear();
            if (!getargs(args, "(iii)", &i, &j, &k))
                return NULL;
        }
        /* ... use i, j and k here ... */
        INCREF(None);
        return None;
    }

(It is possible to think of an extension to the definition of format strings to accommodate this directly, e.g. placing a `|' in a tuple might specify that the remaining arguments are optional. getargs() should then return one more than the number of variables stored into.)

Advanced users note: If you set the `varargs' flag in the method list for a function, the argument will always be a tuple (the `raw argument list'). In this case you must enclose single and empty argument lists in parentheses, e.g. `(s)' and `()'.