Getting Argument Prototypes

Getting Argument Prototypes — Querying Glk function prototypes

Functions

char * gidispatch_prototype ()

Includes

#include <libchimara/glk.h>
#include <libchimara/gi-dispa.h>

Description

There are many possible ways to set up a gluniversal_t array, and it's illegal to call gidispatch_call() with an array which doesn't match the function. Furthermore, some references are passed in, some passed out, and some both. How do you know how to handle the argument list?

One possibility is to recognize each function selector, and set up the arguments appropriately. However, this entails writing special code for each Glk function; which is exactly what we don't want to do.

Instead, you can call gidispatch_prototype().

Functions

gidispatch_prototype ()

char *
gidispatch_prototype (glui32 funcnum);

This returns a string which encodes the proper argument list for the given function. If there is no such function in the library, this returns NULL.

The prototype string for the glk_glomp<!---->() function described above would be: "4IuQa&amp;Iu&amp;Qb:". The "4" is the number of arguments (including the return value, if there is one, which in this case there isn't.) "Iu" denotes an unsigned integer; "Qa" is an opaque object of class 0 (window). "&amp;Iu" is a reference to an unsigned integer, and "&amp;Qb" is a reference to a stream. The colon at the end terminates the argument list; the return value would follow it, if there was one.

Note that the initial number ("4" in this case) is the number of logical arguments, not the number of gluniversal_t objects which will be passed to gidispatch_call(). The glk_glomp<!---->() call uses anywhere from four to six gluniversal_t objects, as demonstrated above.

The basic type codes:

Iu, Is

Unsigned and signed 32-bit integer.

Cn, Cu, Cs

Character, unsigned char, and signed char.

Of course Cn will be the same as either Cu or Cs, depending on the platform. For this reason, Glk avoids using it, but it is included here for completeness.

S

A C-style string (null-terminated array of char). In Glk, strings are always treated as read-only and used immediately; the library does not retain a reference to a string between Glk calls. A Glk call that wants to use writable char arrays will use an array type ("#C"), not string ("S").

U

A zero-terminated array of 32-bit integers. This is primarily intended as a Unicode equivalent of "S". Like "S" strings, "U" strings are read-only and used immediately. A Glk call that wants to use writable Unicode arrays will use an array type ("#Iu") instead of "U".

F

A floating-point value. Glk does not currently use floating-point values, but we might as well define a code for them.

Qa, Qb, Qc...

A reference to an opaque object. The second letter determines which class is involved. (The number of classes can be gleaned from gidispatch_count_classes(); see Interrogating the Interface).

If Glk expands to have more than 26 classes, we'll think of something.

Any type code can be prefixed with one or more of the following characters:

&

A reference to the type; or, if you like, a variable passed by reference. The reference is passed both in and out, so you must copy the value in before calling gidispatch_call() and copy it out afterward.

<

A reference which is pass-out only. The initial value is ignored, so you only need copy out the value after the call.

>

A reference which is pass-in only.

This is not generally used for simple types, but is useful for structures and arrays.

+

Combined with "&", "<", or ">", indicates that a valid reference is mandatory; NULL cannot be passed.

Note that even though the ptrflag gluniversal_t for a "+" reference is always TRUE, it cannot be omitted.

:

The colon separates the arguments from the return value, or terminates the string if there is no return value. Since return values are always non-NULL pass-out references, you may treat ":" as equivalent to "<+". The colon is never combined with any other prefix character.

[...]

Combined with "&", "<", or ">", indicates a structure reference. Between the brackets is a complete argument list encoding string, including the number of arguments.

For example, the prototype string for glk_select() is "1<+[4IuQaIuIu]:" — one argument, which is a pass-out non-NULL reference to a structure, which contains four arguments.

Currently, structures in Glk contain only basic types.

#

Combined with "&", "<", or ">", indicates an array reference. As described above, this encompasses up to three gluniversal_t objects — ptrflag, pointer, and integer length.

Depending on the design of your program, you may wish to pass a pointer directly to your program's memory, or allocate an array and copy the contents in and out. See [Arrays][chimara-Arrays].

!

Combined with "#", indicates that the array is retained by the library. The library will keep a reference to the array; the contents are undefined until further notice. You should not use or copy the contents of the array out after the call, even for "&#!" or "<#!" arrays. Instead, do it when the library releases the array.

For example, glk_stream_open_memory() retains the array that you pass it, and releases it when the stream is closed. The library can notify you automatically when arrays are retained and released; see [Retained Array Registry][gidispatch-set-retained-registry].

The order of these characters and prefixes is not completely arbitrary. Here is a formal grammar for the prototype strings.

Thanks to Neil Cerutti for working this out.

[1] prototype ::= ArgCount [ arg_list ] ':' [ arg ] EOL  
[2] arg_list ::= arg { arg }  
[3] arg ::= TypeName | ref_type  
[4] ref_type ::= RefType [ '+' ] target_type  
[5] target_type ::= TypeName | array | struct  
[6] array ::= '#' [ '!' ] TypeName  
[7] struct ::= '[' ArgCount [ arg_list ] ']'  

TypeName is I[us]|C[nus]|S|U|F|Q[a-z]

ArgCount is \d+

RefType is &|<|>

EOL is end of input

Parameters

funcnum

A selector for the function to be queried.

 

Returns

A string which encodes the prototype of the specified Glk function.