Documented the dispatch functions. Actually there will be two entries left
authorPhilip Chimento <philip.chimento@gmail.com>
Fri, 9 Oct 2009 23:41:05 +0000 (23:41 +0000)
committerPhilip Chimento <philip.chimento@gmail.com>
Fri, 9 Oct 2009 23:41:05 +0000 (23:41 +0000)
out of the documentation because of a bug in gtk-doc. I sent them a patch.

git-svn-id: http://lassie.dyndns-server.com/svn/gargoyle-gtk@137 ddfedd41-794f-dd11-ae45-00112f111e67

configure.ac
docs/reference/.svnignore
docs/reference/Makefile.am
docs/reference/build-selector-table.pl.in [new file with mode: 0644]
docs/reference/chimara-docs.sgml
docs/reference/chimara-sections.txt
docs/reference/dispatch-selectors.sgml [new file with mode: 0644]
docs/reference/dispatch.sgml [new file with mode: 0644]
libchimara/dispatch.c
libchimara/doc.c

index 1c1d5e17a4f15a85a4532a85cbc17ad469f3c026..51a5cf2d215e65c4cf011cb6876a0bc866be4975 100644 (file)
@@ -106,6 +106,7 @@ tests/Makefile
 docs/Makefile
 docs/reference/Makefile
 docs/reference/version.xml
+docs/reference/build-selector-table.pl
 po/Makefile.in
 ])
 # Do it
index 7da551f4837f8e109c456e60a8c6eed2daef9ba5..c35aef5cc5664d85782ae576eab767bd398ea684 100644 (file)
@@ -15,4 +15,5 @@ chimara-decl-list.txt
 chimara-overrides.txt
 chimara-undeclared.txt
 chimara-undocumented.txt
-
+selectors.xml
+build-selector-table.pl
index 6139eaf9bd1cd763c5096556f56f568969155dad..f7f5ee528b81881a54d8687b461a2e4a73344722 100644 (file)
@@ -74,6 +74,7 @@ HTML_IMAGES = \
 
 # Extra SGML files that are included by $(DOC_MAIN_SGML_FILE).
 content_files = version.xml \
+       selectors.xml \
        glk-front-matter.sgml \
        glk-introduction.sgml \
        glk-main-function.sgml \
@@ -84,7 +85,11 @@ content_files = version.xml \
        glk-windows.sgml \
        glk-window-arrangement.sgml \
        glk-display-style.sgml \
-       glk-other-events.sgml
+       glk-other-events.sgml \
+       glk-porting.sgml \
+       dispatch.sgml \
+       blorb.sgml \
+       blorb-library.sgml
 
 # SGML files where gtk-doc abbreviations (#GtkWidget) are expanded
 # These files must be listed here *and* in content_files
@@ -112,7 +117,8 @@ EXTRA_DIST += version.xml.in
 # Files not to distribute
 # for --rebuild-types in $(SCAN_OPTIONS), e.g. $(DOC_MODULE).types
 # for --rebuild-sections in $(SCAN_OPTIONS), e.g. $(DOC_MODULE)-sections.txt
-DISTCLEANFILES = $(DOC_MODULE)-overrides.txt
+CLEANFILES += selectors.xml
+DISTCLEANFILES = version.xml $(DOC_MODULE)-overrides.txt
 
 # Uncomment this if you want your docs-status tested during 'make check'
 # Comment this while not all symbols are documented, otherwise distcheck fails
@@ -120,3 +126,9 @@ DISTCLEANFILES = $(DOC_MODULE)-overrides.txt
 #TESTS_ENVIRONMENT = cd $(srcdir) &&
 #TESTS = $(GTKDOC_CHECK)
 #endif
+
+dist_noinst_SCRIPTS = build-selector-table.pl
+
+selectors.xml: $(srcdir)/../../libchimara/gi_dispa.c
+       $(PERL) build-selector-table.pl $< > $@
+
diff --git a/docs/reference/build-selector-table.pl.in b/docs/reference/build-selector-table.pl.in
new file mode 100644 (file)
index 0000000..80e8a48
--- /dev/null
@@ -0,0 +1,32 @@
+#!@PERL@ -w
+#
+# Automatically builds section 11.1.6, "Table of Selectors", from the C code
+# in gi_dispa.c.
+
+my $in_list = 0;
+
+print "<variablelist>\n";
+
+while (<>) {
+       chomp;
+       if (/function_table\s*\[\]\s*=\s*{\s*$/) {
+               $in_list = 1;
+               next;
+       }
+       if ($in_list) {
+               next if /^#/;
+               last if /^};/;
+               /{\s*(0x[0-9a-fA-F]{4}),\s*(\w*).*/;
+               print "<varlistentry>\n";
+               print "  <term><code>$1</code></term>\n";
+               my $functionname = $2;
+               my $linkname = '"' . $2 . '"';
+               $linkname =~ s/_/-/g;
+               print "  <listitem><para>\n";
+               print "    <link linkend=$linkname><function>$functionname()</function></link>\n";
+               print "  </para></listitem>\n";
+               print "</varlistentry>\n";
+       }
+}
+
+print "</variablelist>\n";
index 208c237d882c103c78219e14b7c6b6de5f3b5725..1f8cf2db5f0c004b486fa2acbae341a29b17abcb 100644 (file)
     <xi:include href="glk-porting.sgml"/>
    
     <!-- Chapter 11. Appendices -->
-<!--    <appendix>
+    <appendix>
       <title>The Dispatch Layer</title>
+      <xi:include href="dispatch.sgml"/>
+      <xi:include href="xml/dispatch-interrogating.xml"/>
+      <xi:include href="xml/dispatch-dispatching.xml"/>
+      <xi:include href="xml/dispatch-prototypes.xml"/>
+      <xi:include href="xml/dispatch-library-functions.xml"/>
+      <xi:include href="dispatch-selectors.sgml"/>
     </appendix>
--->    
+
     <appendix>
       <title>The Blorb Layer</title>
       <xi:include href="blorb.sgml"/>
index 2281bfb3d2399d5e3919931608f3ceb403bed988..f933b2da9c8e198e3a7bef6cd8db305e2897a914 100644 (file)
@@ -481,6 +481,46 @@ glk_cancel_hyperlink_event
 GLK_MODULE_HYPERLINKS
 </SECTION>
 
+<SECTION>
+<FILE>dispatch-interrogating</FILE>
+<TITLE>Interrogating the Interface</TITLE>
+gidispatch_count_classes
+gidispatch_count_intconst
+gidispatch_get_intconst
+gidispatch_intconst_t
+gidispatch_count_functions
+gidispatch_get_function
+gidispatch_function_t
+gidispatch_get_function_by_id
+<SUBSECTION Constants>
+gidisp_Class_Window
+gidisp_Class_Stream
+gidisp_Class_Fileref
+gidisp_Class_Schannel
+</SECTION>
+
+<SECTION>
+<FILE>dispatch-dispatching</FILE>
+<TITLE>Dispatching</TITLE>
+gidispatch_call
+gluniversal_t
+</SECTION>
+
+<SECTION>
+<FILE>dispatch-prototypes</FILE>
+<TITLE>Getting Argument Prototypes</TITLE>
+gidispatch_prototype
+</SECTION>
+
+<SECTION>
+<FILE>dispatch-library-functions</FILE>
+<TITLE>Functions the Library Must Provide</TITLE>
+gidispatch_set_object_registry
+gidispatch_rock_t
+gidispatch_get_objrock
+gidispatch_set_retained_registry
+</SECTION>
+
 <SECTION>
 <FILE>blorb-program</FILE>
 <TITLE>What the Program Does</TITLE>
diff --git a/docs/reference/dispatch-selectors.sgml b/docs/reference/dispatch-selectors.sgml
new file mode 100644 (file)
index 0000000..6489324
--- /dev/null
@@ -0,0 +1,34 @@
+<?xml version="1.0"?>
+<!DOCTYPE book PUBLIC "-//OASIS//DTD DocBook XML V4.1.2//EN"
+               "http://www.oasis-open.org/docbook/xml/4.1.2/docbookx.dtd" [
+<!ENTITY selectors SYSTEM "selectors.xml">
+]>
+<refentry id="chimara-Table-of-Selectors">
+<refmeta>
+<refentrytitle>Table of Selectors</refentrytitle>
+<manvolnum>3</manvolnum>
+<refmiscinfo>CHIMARA Library</refmiscinfo>
+</refmeta>
+<refnamediv>
+<refname>Table of Selectors</refname>
+<refpurpose>Table of dispatch selectors for Glk functions</refpurpose>
+</refnamediv>
+<refsect1>
+<title>Description</title>
+<para>
+These values, and the values used for future Glk calls, are integers in the range <code>0x0001</code> to <code>0xFFFF</code> (1 to 65535). The values are not sequential; they are divided into groups, roughly by category. Zero is not the selector of any
+Glk call, so it may be used for a null value.
+</para>
+&selectors;
+<para>
+Note that <function>glk_main()</function> does not have a selector, because it's provided by your program, not the library.
+</para>
+<para>
+There is no way to use these selectors directly in the Glk API.
+<note><para>
+An earlier version of Glk had gestalt selectors <code>gestalt_FunctionNameToID</code> and <code>gestalt_FunctionIDToName</code>, but these have been withdrawn.
+</para></note>
+They are defined and used only in the dispatch layer.
+</para>
+</refsect1>
+</refentry>
diff --git a/docs/reference/dispatch.sgml b/docs/reference/dispatch.sgml
new file mode 100644 (file)
index 0000000..7a811de
--- /dev/null
@@ -0,0 +1,39 @@
+<?xml version="1.0"?>
+<!DOCTYPE book PUBLIC "-//OASIS//DTD DocBook XML V4.1.2//EN"
+               "http://www.oasis-open.org/docbook/xml/4.1.2/docbookx.dtd" [
+]>
+<refentry id="chimara-The-Dispatch-Layer">
+<refmeta>
+<refentrytitle>The Dispatch Layer</refentrytitle>
+<manvolnum>3</manvolnum>
+<refmiscinfo>CHIMARA Library</refmiscinfo>
+</refmeta>
+<refnamediv>
+<refname>The Dispatch Layer</refname>
+<refpurpose>Calling Glk functions dynamically</refpurpose>
+</refnamediv>
+<refsect1>
+<title>Description</title>
+<para>
+The material described in this section is not part of the Glk API per se. It is an external layer, lying on top of Glk, which allows a program to invoke Glk dynamically &mdash; determining the capabilities and interfaces of Glk at run-time.
+</para>
+<para>
+This is most useful for virtual machines and other run-time systems, which want to use Glk without being bound to a particular version of the Glk API. In other words, a VM can export Glk to VM programs, without hard-wiring a list of Glk functions within itself. If a new Glk library is released, with new functions, the VM can simply link in the library; the new functions will be available to VM programs without further work.
+</para>
+<para>
+If you are writing a C program which uses the Glk API, you can ignore this section entirely. If you are writing a VM which uses Glk, you need to read it. If you are implementing a Glk library, you should also read it. (There are some additional interfaces which your library must support for the dispatch layer to work right.) 
+</para>
+<refsect2 id="chimara-How-This-Works">
+<title>How This Works</title>
+<para>
+The dispatch layer is implemented in a C source file, <filename>gi_dispa.c</filename>, and its header, <filename class="headerfile">gi_dispa.h</filename>. This code is platform-independent &mdash; it is identical in every library, just as the <filename class="headerfile">glk.h</filename> header file is identical in every library. Each library author should download the <filename>gi_dispa.c</filename> and <filename class="headerfile">gi_dispa.h</filename> files from the Glk web site, and compile them unchanged into the library.
+</para>
+<para>
+This code is mostly external to Glk; it operates by calling the documented Glk API, not library internals. This is how <filename>gi_dispa.c</filename> can be platform-independent. However, the dividing line is not perfect. There are a few extra functions, not part of the Glk API, which the library must implement; <filename>gi_dispa.c</filename> (and no one else) calls these functions. These functions are simple and should not make life much harder for library implementors.
+</para>
+<para>
+The dispatch layer then provides a dispatch API. The heart of this is the <link linkend="gidispatch-call"><function>gidispatch_call()</function></link> function, which allows you to call <emphasis>any</emphasis> Glk function (specified by number) and pass in a list of arguments in a standardized way. You may also make use of <link linkend="gidispatch-prototype"><function>gidispatch_prototype()</function></link>, which gives you the proper format of that list for each function. Ancilliary functions let you enumerate the functions and constants in the Glk API. 
+</para>
+</refsect2>
+</refsect1>
+</refentry>
index b1f84dacd6d40c6937460961e6e394df30a69b5e..895d2e7e4c249dd16e1e6e36489591856f4e84c0 100644 (file)
@@ -6,6 +6,66 @@
 
 extern GPrivate *glk_data_key;
 
+/**
+ * gidispatch_set_object_registry:
+ * @regi: Function to call whenever an opaque object is created.
+ * @unregi: Function to call whenever an opaque object is destroyed.
+ *
+ * The Glk API refers to opaque objects by pointer; but a VM probably cannot 
+ * store pointers to native memory. Therefore, a VM program will want to keep a
+ * VM-accessible collection of opaque objects.
+ * 
+ * <note><para>
+ *   For example, it might keep a hash table for each opaque object class,
+ *   mapping integer identifiers to object pointers.
+ * </para></note>
+ * 
+ * To make this possible, a Glk library must implement 
+ * gidispatch_set_object_registry().
+ * 
+ * Your program calls gidispatch_set_object_registry() early (before it begins
+ * actually executing VM code.) You pass in two function pointers, matching the
+ * following prototypes:
+ * |[
+ * #gidispatch_rock_t my_vm_reg_object(void *obj, #glui32 objclass);
+ * void my_vm_unreg_object(void *obj, #glui32 objclass, #gidispatch_rock_t objrock);
+ * ]|
+ * 
+ * Whenever the Glk library creates an object, it will call my_vm_reg_object(). 
+ * It will pass the object pointer and the class number (from 0 to
+ * <inlineequation><mathphrase>N - 1</mathphrase><alt>N - 
+ * 1</alt></inlineequation>, where N is the value returned by
+ * gidispatch_count_classes().)
+ * 
+ * You can return any value in the #gidispatch_rock_t object; the library will
+ * stash this away inside the object.
+ * 
+ * <note><para>
+ *   Note that this is entirely separate from the regular Glk rock, which is
+ *   always a #glui32 and can be set independently.
+ * </para></note>
+ * 
+ * Whenever the Glk library destroys an object, it will call
+ * my_vm_unreg_object(). It passes you the object pointer, class number, and the
+ * object rock.
+ *
+ * One significant detail: It is possible that some Glk objects will already
+ * exist when your glk_main() function is called.
+ * 
+ * <note><para>
+ *   For example, MacGlk can open a stream when the user double-clicks a file;
+ *   this occurs before glk_main().
+ * </para></note>
+ * 
+ * So when you call gidispatch_set_object_registry(), it may immediately call
+ * your my_vm_reg_object() callback, notifying you of the existing objects. You
+ * must be prepared for this possibility.
+ * 
+ * <note><para>
+ *   If you are keeping hash tables, for example, create them before you call
+ *   gidispatch_set_object_registry().
+ * </para></note>
+ */
 void 
 gidispatch_set_object_registry(gidispatch_rock_t (*regi)(void *obj, glui32 objclass), void (*unregi)(void *obj, glui32 objclass, gidispatch_rock_t objrock))
 {
@@ -29,9 +89,26 @@ gidispatch_set_object_registry(gidispatch_rock_t (*regi)(void *obj, glui32 objcl
     }
 }
 
+/**
+ * gidispatch_get_objrock:
+ * @obj: An opaque object.
+ * @objclass: One of #gidisp_Class_Window, #gidisp_Class_Stream,
+ * #gidisp_Class_Fileref, or #gidisp_Class_Schannel.
+ *
+ * You can, at any time, get the object rock of an object. The library
+ * implements this function.
+ * 
+ * With this and your two callbacks, you can maintain (say) a hash table for
+ * each object class, and easily convert back and forth between hash table keys
+ * and Glk object pointers. A more sophisticated run-time system (such as Java)
+ * could create a typed VM object for every Glk object, thus allowing VM code to
+ * manipulate Glk objects intelligently.
+ */
 gidispatch_rock_t 
 gidispatch_get_objrock(void *obj, glui32 objclass)
 {
+       g_return_val_if_fail(obj, NULL);
+       
        switch(objclass) 
        {
                case gidisp_Class_Window:
@@ -49,6 +126,61 @@ gidispatch_get_objrock(void *obj, glui32 objclass)
        }
 }
 
+/**
+ * gidispatch_set_retained_registry:
+ * @regi: Function to call whenever the Glk library assumes ownership of an
+ * array.
+ * @unregi: Function to call whenever the Glk library releases ownership of an
+ * array.
+ *
+ * A few Glk functions take an array and hold onto it. The memory is 
+ * <quote>owned</quote> by the library until some future Glk call releases it.
+ * While the library retains the array, your program should not read, write,
+ * move, or deallocate it. When the library releases it, the contents are in
+ * their final form, and you can copy them out (if appropriate) and dispose of
+ * the memory as you wish.
+ * 
+ * To allow this, the library implements gidispatch_set_retained_registry().
+ * 
+ * Again, you pass in two function pointers:
+ * |[
+ * #gidispatch_rock_t my_vm_reg_array(void *array, #glui32 len, char *typecode);
+ * void my_vm_unreg_array(void *array, #glui32 len, char *typecode, #gidispatch_rock_t objrock);
+ * ]|
+ *
+ * Whenever a Glk function retains an array, it will call my_vm_reg_array().
+ * This occurs only if you pass an array to an argument with the
+ * <code>"#!"</code> prefix.
+ *
+ * <note><para>
+ *   But not in every such case. Wait for the my_vm_reg_array() call to confirm
+ *   it.
+ * </para></note>
+ *
+ * The library passes the array and its length, exactly as you put them in the
+ * #gluniversal_t array. It also passes the string which describes the argument.
+ *
+ * <note><para>
+ *   Currently, the only calls that retain arrays are glk_request_line_event(),
+ *   glk_stream_open_memory(), glk_request_line_event_uni(), and
+ *   glk_stream_open_memory_uni(). The first two of these use arrays of
+ *   characters, so the string is <code>"&+#!Cn"</code>. The latter two use
+ *   arrays of #glui32, so the string is <code>"&+#!Iu"</code>.
+ * </para></note>
+ * 
+ * You can return any value in the #gidispatch_rock_t object; the library will
+ * stash this away with the array.
+ * 
+ * When a Glk function releases a retained array, it will call
+ * my_vm_unreg_array(). It passes back the same @array, @len, and @typecode
+ * parameters, as well as the #gidispatch_rock_t you returned from
+ * my_vm_reg_array().
+ * 
+ * With these callbacks, you can maintain a collection of retained arrays. You
+ * can use this to copy data from C arrays to your own data structures, or keep
+ * relocatable memory locked, or prevent a garbage-collection system from
+ * deallocating an array while Glk is writing to it.
+ */
 void 
 gidispatch_set_retained_registry(gidispatch_rock_t (*regi)(void *array, glui32 len, char *typecode), void (*unregi)(void *array, glui32 len, char *typecode, gidispatch_rock_t objrock))
 {
index c9c6e33c936f59fb483142f6fb2bd77a8639d819..092eda2ee0fd874666dcc767d02f3acc4c082ddd 100644 (file)
  * else.
  */
 
+/**
+ * SECTION:dispatch-interrogating
+ * @short_description: Finding out what functions the Glk library exports
+ * @include: libchimara/glk.h, libchimara/gi_dispa.h
+ *
+ * These are the ancilliary functions that let you enumerate.
+ */
+/**
+ * SECTION:dispatch-dispatching
+ * @short_description: Dispatching the call to the Glk library
+ * @include: libchimara/glk.h, libchimara/gi_dispa.h
+ */
+/**
+ * SECTION:dispatch-prototypes
+ * @short_description: Querying Glk function prototypes
+ * @include: libchimara/glk.h, libchimara/gi_dispa.h
+ *
+ * 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(). 
+ */
+
+/**
+ * SECTION:dispatch-library-functions
+ * @short_description: Platform-dependent dispatch layer functions
+ * @include: libchimara/glk.h, libchimara/gi_dispa.h
+ *
+ * Ideally, the three layers &mdash; program, dispatch layer, Glk library
+ * &mdash; would be completely modular; each would refer only to the layers
+ * beneath it. Sadly, there are a few places where the library must notify the
+ * program that something has happened. Worse, these situations are only
+ * relevant to programs which use the dispatch layer, and then only some of
+ * those.
+ * 
+ * Since C is uncomfortable with the concept of calling functions which may not
+ * exist, Glk handles this with call-back function pointers. The program can
+ * pass callbacks in to the library; if it does, the library will call them, and
+ * if not, the library doesn't try.
+ * 
+ * These callbacks are optional, in the sense that the program may or may not
+ * set them. However, any library which wants to interoperate with the dispatch
+ * layer must <emphasis>allow</emphasis> the program to set them; it is the
+ * program's choice. The library does this by implementing
+ * <code>set_registry functions</code> &mdash; the functions to which the
+ * program passes its callbacks.
+ * 
+ * <note><para>
+ *   Even though these callbacks and the functions to set them are declared in
+ *   <filename class="headerfile">gi_dispa.h</filename>, they are not defined in
+ *   <filename>gi_dispa.c</filename>. The dispatch layer merely coordinates
+ *   them. The program defines the callback functions; the library calls them.
+ * </para></note>
+ */
+
 /** 
  * SECTION:blorb-program
  * @short_description: How to use the Blorb layer in your program
  * A value for %stylehint_Justification representing right-justified text.
  */
 
+/*---------- TYPES, FUNCTIONS AND CONSTANTS FROM GI_DISPA.H ------------------*/
+
+/**
+ * gidispatch_count_classes:
+ * 
+ * Returns the number of opaque object classes used by the library. You will
+ * need to know this if you want to keep track of opaque objects as they are
+ * created; see <link linkend="gidispatch-set-object-registry">Opaque Object
+ * Registry</link>.
+ * 
+ * As of Glk API 0.7.0, there are four classes: windows, streams, filerefs, and
+ * sound channels (numbered 0, 1, 2, and 3 respectively.)
+ *
+ * Returns: Number of opaque object classes used by the library.
+ */
+/**
+ * gidispatch_count_intconst:
+ *
+ * Returns the number of integer constants exported by the library.
+ *
+ * Returns: Number of integer constants exported by the library.
+ */
+/**
+ * gidispatch_get_intconst:
+ * @index: Unique integer index of the integer constant.
+ *
+ * Returns a structure describing an integer constant which the library exports.
+ * These are, roughly, all the constants defined in the <filename
+ * class="headerfile">glk.h</filename> file. @index can range from 0 to
+ * <inlineequation><mathphrase>N - 1</mathphrase><alt>N - 
+ * 1</alt></inlineequation>, where N is the value returned by 
+ * gidispatch_count_intconst().
+ *
+ * Returns: A #gidispatch_intconst_t structure describing the integer constant.
+ */
+
+/**
+ * gidispatch_intconst_t:
+ * @name: Symbolic name of the integer constant.
+ * @val: Value of the integer constant.
+ *
+ * This structure simply contains a string and a value. The string is a
+ * symbolic name of the value, and can be re-exported to anyone interested in
+ * using Glk constants.
+ */
+/**
+ * gidispatch_count_functions:
+ *
+ * Returns the number of functions exported by the library.
+ *
+ * Returns: Number of functions exported by the library.
+ */
+/**
+ * gidispatch_get_function:
+ * @index: Unique integer index of the function.
+ *
+ * Returns a structure describing a Glk function. @index can range from 0 to
+ * <inlineequation><mathphrase>N - 1</mathphrase><alt>N - 
+ * 1</alt></inlineequation>, where N is the value returned by 
+ * gidispatch_count_functions().
+ *
+ * Returns: A #gidispatch_function_t structure describing the function.
+ */
+/**
+ * gidispatch_function_t:
+ * @id: Dispatch selector of the function.
+ * @fnptr: Pointer to the function.
+ * @name: Name of the function, without the <code>glk_</code> prefix.
+ *
+ * The @id field is a selector &mdash; a numeric constant used to refer to the
+ * function in question. @name is the function name, as it is given in the
+ * <filename class="headerfile">glk.h</filename> file, but without the 
+ * <quote><code>glk_</code></quote> prefix. And @fnptr is the address of the
+ * function itself.
+ *
+ * <note><para>
+ *   This is included because it might be useful, but it is not recommended. To
+ *   call an arbitrary Glk function, you should use gidispatch_call().
+ * </para></note>
+ *
+ * See <link linkend="chimara-Table-of-Selectors">Table of Selectors</link> for
+ * the selector definitions. See <link 
+ * linkend="chimara-Dispatching">Dispatching</link> for more about calling Glk
+ * functions by selector.
+ */
+/**
+ * gidispatch_get_function_by_id:
+ * @id: A selector.
+ *
+ * Returns a structure describing the Glk function with selector @id. If there 
+ * is no such function in the library, this returns %NULL.
+ *
+ * Returns: a #gidispatch_function_t structure, or %NULL.
+ */
+/**
+ * gidispatch_call:
+ * @funcnum: Selector of the function to call.
+ * @numargs: Length of @arglist.
+ * @arglist: List of arguments to pass to the function.
+ *
+ * @funcnum is the function number to invoke; see <link 
+ * linkend="chimara-Table-of-Selectors">Table of Selectors</link>. @arglist is
+ * the list of arguments, and @numargs is the length of the list.
+ * 
+ * The arguments are all stored as #gluniversal_t objects. 
+ * </para><refsect3 id="chimara-Basic-Types"><title>Basic Types</title><para>
+ * Numeric arguments are passed in the obvious way &mdash; one argument per
+ * #gluniversal_t, with the @uint or @sint field set to the numeric value.
+ * Characters and strings are also passed in this way &mdash; #char<!---->s in
+ * the @uch, @sch, or @ch fields (depending on whether the #char is signed) and
+ * strings in the @charstr field. Opaque objects (windows, streams, etc) are
+ * passed in the @opaqueref field (which is <code>void*</code>, in order to
+ * handle all opaque pointer types.)
+ * 
+ * However, pointers (other than C strings), arrays, and structures complicate
+ * life. So do return values.
+ * </para></refsect3>
+ * <refsect3 id="chimara-References"><title>References</title><para>
+ * A reference to a numeric type or object reference &mdash; that is,
+ * <code>#glui32*</code>, <code>#winid_t*</code>, and so on &mdash; takes
+ * <emphasis>one or two</emphasis> #gluniversal_t objects. The first is a flag
+ * indicating whether the reference argument is %NULL or not. The @ptrflag field
+ * of this #gluniversal_t should be %FALSE if the reference is %NULL, and %TRUE
+ * otherwise. If %FALSE, that is the end of the argument; you should not use a
+ * #gluniversal_t to explicitly store the %NULL reference. If the flag is %TRUE,
+ * you must then put a #gluniversal_t storing the base type of the reference.
+ *
+ * For example, consider a hypothetical function, with selector 
+ * <code>0xABCD</code>:
+ * |[ 
+ * void glk_glomp(#glui32 num, #winid_t win, #glui32 *numref, #strid_t *strref);
+ * ]|
+ * ...and the calls:
+ * |[
+ * #glui32 value;
+ * #winid_t mainwin;
+ * #strid_t gamefile;
+ * glk_glomp(5, mainwin, &value, &gamefile);
+ * ]|
+ *
+ * To perform this through gidispatch_call(), you would do the following:
+ * |[
+ * #gluniversal_t arglist[6];
+ * arglist[0].uint = 5;
+ * arglist[1].opaqueref = mainwin;
+ * arglist[2].ptrflag = TRUE;
+ * arglist[3].uint = value;
+ * arglist[4].ptrflag = TRUE;
+ * arglist[5].opaqueref = gamefile;
+ * #gidispatch_call(0xABCD, 6, arglist);
+ * value = arglist[3].uint;
+ * gamefile = arglist[5].opaqueref;
+ * ]|
+ * 
+ * Note that you copy the value of the reference arguments into and out of
+ * @arglist. Of course, it may be that glk_glomp() only uses these as pass-out
+ * references or pass-in references; if so, you could skip copying in or out.
+ *
+ * For further examples:
+ * |[
+ * glk_glomp(7, mainwin, NULL, NULL);
+ * ...or...
+ * #gluniversal_t arglist[4];
+ * arglist[0].uint = 7;
+ * arglist[1].opaqueref = mainwin;
+ * arglist[2].ptrflag = FALSE;
+ * arglist[3].ptrflag = FALSE;
+ * #gidispatch_call(0xABCD, 4, arglist);
+ * ]|
+ *
+ * |[
+ * glk_glomp(13, NULL, NULL, &gamefile);
+ * ...or...
+ * #gluniversal_t arglist[5];
+ * arglist[0].uint = 13;
+ * arglist[1].opaqueref = NULL;
+ * arglist[2].ptrflag = FALSE;
+ * arglist[3].ptrflag = TRUE;
+ * arglist[4].opaqueref = gamefile;
+ * #gidispatch_call(0xABCD, 5, arglist);
+ * gamefile = arglist[4].opaqueref;
+ * ]|
+ *
+ * |[
+ * glk_glomp(17, NULL, &value, NULL);
+ * ...or...
+ * #gluniversal_t arglist[5];
+ * arglist[0].uint = 17;
+ * arglist[1].opaqueref = NULL;
+ * arglist[2].ptrflag = TRUE;
+ * arglist[3].uint = value;
+ * arglist[4].ptrflag = FALSE;
+ * #gidispatch_call(0xABCD, 5, arglist);
+ * value = arglist[3].uint;
+ * ]|
+ * 
+ * As you see, the length of @arglist depends on how many of the reference
+ * arguments are %NULL.
+ * </para></refsect3>
+ * <refsect3 id="chimara-Structures"><title>Structures</title><para>
+ * A structure pointer is represented by a single @ptrflag, possibly followed by
+ * a sequence of #gluniversal_t objects (one for each field of the structure.)
+ * Again, if the structure pointer is non-%NULL, the @ptrflag should be %TRUE
+ * and be followed by values; if not, the @ptrflag should be %NULL and stands
+ * alone.
+ * 
+ * For example, the function glk_select() can be invoked as follows:
+ * |[
+ * #event_t ev;
+ * #gluniversal_t arglist[5];
+ * arglist[0].ptrflag = TRUE;
+ * #gidispatch_call(0x00C0, 5, arglist);
+ * ev.type = arglist[1].uint;
+ * ev.win = arglist[2].opaqueref;
+ * ev.val1 = arglist[3].uint;
+ * ev.val2 = arglist[4].uint;
+ * ]|
+ * 
+ * Since the structure passed to glk_select() is a pass-out reference (the entry
+ * values are ignored), you don't need to fill in <code>arglist[1..4]</code>
+ * before calling gidispatch_call().
+ * 
+ * <note><para>
+ *   Theoretically, you would invoke <code>#glk_select(%NULL)</code> by setting'
+ *   <code>arglist[0].ptrflag</code> to %FALSE, and using a one-element @arglist
+ *   instead of five-element. But it's illegal to pass %NULL to glk_select(). So
+ *   you cannot actually do this.
+ * </para></note></para></refsect3>
+ * <refsect3 id="chimara-Arrays"><title>Arrays</title><para>
+ * In the Glk API, an array argument is always followed by a numeric argument
+ * giving the array's length. These two C arguments are a single logical
+ * argument, which is represented by <emphasis>one or three</emphasis>
+ * #gluniversal_t objects. The first is a @ptrflag, indicating whether the
+ * argument is %NULL or not. The second is a pointer, stored in the @array
+ * field. The third is the array length, stored in the @uint field. And again,
+ * if the @ptrflag is %NULL, the following two are omitted.
+ * 
+ * For example, the function glk_put_buffer() can be invoked as follows:
+ * |[
+ * #char buf[64];
+ * #glui32 len = 64;
+ * #glk_put_buffer(buf, len);
+ * ...or...
+ * #gluniversal_t arglist[3];
+ * arglist[0].ptrflag = TRUE;
+ * arglist[1].array = buf;
+ * arglist[2].uint = len;
+ * #gidispatch_call(0x0084, 3, arglist);
+ * ]|
+ * 
+ * Since you are passing a C char array to gidispatch_call(), the contents will
+ * be read directly from that. There is no need to copy data into @arglist, as
+ * you would for a basic type.
+ * 
+ * If you are implementing a VM whose native representation of char arrays is
+ * more complex, you will have to do more work. You should allocate a C char
+ * array, copy your characters into it, make the call, and then free the array.
+ *
+ * <note><para>
+ *   glk_put_buffer() does not modify the array passed to it, so there is no
+ *   need to copy the characters out.
+ * </para></note></para></refsect3>
+ * <refsect3 id="chimara-Return-Values"><title>Return Values</title><para>
+ * The return value of a function is not treated specially. It is simply
+ * considered to be a pass-out reference argument which may not be %NULL. It
+ * comes after all the other arguments of the function.
+ * 
+ * For example, the function glk_window_get_rock() can be invoked as follows:
+ * |[
+ * #glui32 rock;
+ * #winid_t win;
+ * rock = #glk_window_get_rock(win);
+ * ...or...
+ * #gluniversal_t arglist[3];
+ * arglist[0].opaqueref = win;
+ * arglist[1].ptrflag = TRUE;
+ * #gidispatch_call(0x0021, 3, arglist);
+ * rock = arglist[2].uint;
+ * ]|
+ * </para></refsect3><para>
+ */
+
+/**
+ * gluniversal_t:
+ * @uint: Stores a #glui32.
+ * @sint: Stores a #glsi32.
+ * @opaqueref: Stores a #winid_t, #strid_t, #frefid_t, or #schanid_t.
+ * @uch: Stores an #unsigned #char.
+ * @sch: Stores a #signed #char.
+ * @ch: Stores a #char with the default signedness.
+ * @charstr: Stores a %NULL-terminated string.
+ * @array: Stores a pointer to an array, and should be followed by another 
+ * #gluniversal_t with the array length stored in the @uint member.
+ * @ptrflag: If %FALSE, represents an opaque reference or array that is %NULL,
+ * in which case it represents the entire argument. If %TRUE, should be followed
+ * by another #gluniversal_t with the pointer in its @opaqueref or @array field.
+ *
+ * This is a union, encompassing all the types that can be passed to Glk
+ * functions.
+ */
+/**
+ * gidispatch_prototype:
+ * @funcnum: A selector for the function to be queried.
+ *
+ * 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:
+ * <code>"4IuQa&amp;Iu&amp;Qb:"</code>. The <code>"4"</code> is the number of
+ * arguments (including the return value, if there is one, which in this case
+ * there isn't.) <code>"Iu"</code> denotes an unsigned integer;
+ * <code>"Qa"</code> is an opaque object of class 0 (window).
+ * <code>"&amp;Iu"</code> is a <emphasis>reference</emphasis> to an unsigned
+ * integer, and <code>"&amp;Qb"</code> 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 (<code>"4"</code> 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:
+ * <variablelist>
+ * <varlistentry>
+ *   <term><code>Iu, Is</code></term>
+ *   <listitem><para>Unsigned and signed 32-bit integer.</para></listitem>
+ * </varlistentry>
+ * <varlistentry>
+ *   <term><code>Cn, Cu, Cs</code></term>
+ *   <listitem><para>Character, #unsigned #char, and #signed #char.</para>
+ *     <note><para>Of course <code>Cn</code> will be the same as either 
+ *     <code>Cu</code> or <code>Cs</code>, depending on the platform. For this
+ *     reason, Glk avoids using it, but it is included here for completeness.
+ *     </para></note>
+ *   </listitem>
+ * </varlistentry>
+ * <varlistentry>
+ *   <term><code>S</code></term>
+ *   <listitem><para>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 
+ *   (<code>"&num;C"</code>), not string (<code>"S"</code>).</para></listitem>
+ * </varlistentry>
+ * <varlistentry>
+ *   <term><code>U</code></term>
+ *   <listitem><para>A zero-terminated array of 32-bit integers. This is
+ *   primarily intended as a Unicode equivalent of <code>"S"</code>. Like 
+ *   <code>"S"</code> strings, <code>"U"</code> strings are read-only and used
+ *   immediately. A Glk call that wants to use writable Unicode arrays will use
+ *   an array type (<code>"&num;Iu"</code>) instead of <code>"U"</code>.</para>
+ *   </listitem>
+ * </varlistentry>
+ * <varlistentry>
+ *   <term><code>F</code></term>
+ *   <listitem><para>A floating-point value. Glk does not currently use
+ *   floating-point values, but we might as well define a code for them.</para>
+ *   </listitem>
+ * </varlistentry>
+ * <varlistentry>
+ *   <term><code>Qa, Qb, Qc...</code></term>
+ *   <listitem><para>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 <link 
+ *   linkend="chimara-Interrogating-the-Interface">Interrogating the
+ *   Interface</link>).</para>
+ *   <note><para>
+ *     If Glk expands to have more than 26 classes, we'll think of something.
+ *   </para></note></listitem>
+ * </varlistentry>
+ * </variablelist>
+ * Any type code can be prefixed with one or more of the following characters
+ * (order does not matter):
+ * <variablelist>
+ * <varlistentry>
+ *   <term><code>&amp;</code></term>
+ *   <listitem><para>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.</para>
+ *   </listitem>
+ * </varlistentry>
+ * <varlistentry>
+ *   <term><code>&lt;</code></term>
+ *   <listitem><para>A reference which is pass-out only. The initial value is
+ *   ignored, so you only need copy out the value after the call.</para>
+ *   </listitem>
+ * </varlistentry>
+ * <varlistentry>
+ *   <term><code>&gt;</code></term>
+ *   <listitem><para>A reference which is pass-in only.</para>
+ *   <note><para>
+ *     This is not generally used for simple types, but is useful for structures
+ *     and arrays.
+ *   </para></note></listitem>
+ * </varlistentry>
+ * <varlistentry>
+ *   <term><code>+</code></term>
+ *   <listitem><para>Combined with <code>"&"</code>, <code>"&lt;"</code>, or 
+ *   <code>"&gt;"</code>, indicates that a valid reference is mandatory; %NULL
+ *   cannot be passed.</para>
+ *   <note><para>
+ *     Note that even though the @ptrflag #gluniversal_t for a <code>"+"</code>
+ *     reference is always %TRUE, it cannot be omitted.
+ *   </para></note></listitem>
+ * </varlistentry>
+ * <varlistentry>
+ *   <term><code>:</code></term>
+ *   <listitem><para>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 <code>":"</code> as
+ *   equivalent to <code>"&lt;+"</code>. The colon is never combined with any
+ *   other prefix character.</para></listitem>
+ * </varlistentry>
+ * <varlistentry>
+ *   <term><code>[...]</code></term>
+ *   <listitem><para>Combined with <code>"&amp;"</code>, <code>"&lt;"</code>, or 
+ *   <code>"&gt;"</code>, indicates a structure reference. Between the brackets
+ *   is a complete argument list encoding string, including the number of
+ *   arguments.</para>
+ *   <note><para>
+ *     For example, the prototype string for glk_select() is
+ *     <code>"1&lt;+[4IuQaIuIu]:"</code> &mdash; one argument, which is a
+ *     pass-out non-%NULL reference to a structure, which contains four
+ *     arguments.
+ *   </para></note>
+ *   <para>Currently, structures in Glk contain only basic types.</para>
+ *   </listitem>
+ * </varlistentry>
+ * <varlistentry>
+ *   <term><code>&num;</code></term>
+ *   <listitem><para>Combined with <code>"&amp;"</code>, <code>"&lt;"</code>, or 
+ *   <code>"&gt;"</code>, indicates an array reference. As described above, this
+ *   encompasses up to three #gluniversal_t objects &mdash; @ptrflag, pointer,
+ *   and integer length.</para>
+ *   <note><para>
+ *     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 <link linkend="chimara-Arrays">Arrays</link>.
+ *   </para></note></listitem>
+ * </varlistentry>
+ * <varlistentry>
+ *   <term><code>!</code></term>
+ *   <listitem><para>Combined with <code>"&num;"</code>, 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 
+ *   <code>"&amp;&num;!"</code> or <code>"&lt;&num;!"</code> arrays. Instead, do
+ *   it when the library releases the array.</para>
+ *   <note><para>
+ *     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 <link
+ *     linkend="gidispatch-set-retained-registry">Retained Array
+ *     Registry</link>.
+ *   </para></note></listitem>
+ * </varlistentry>
+ * </variablelist>
+ *
+ * Returns: A string which encodes the prototype of the specified Glk function.
+ */
+
+/**
+ * gidisp_Class_Window:
+ *
+ * Represents a #winid_t opaque object.
+ */
+/**
+ * gidisp_Class_Stream:
+ *
+ * Represents a #strid_t opaque object.
+ */
+/**
+ * gidisp_Class_Fileref:
+ *
+ * Represents a #frefid_t opaque object.
+ */
+
+/**
+ * gidisp_Class_Schannel:
+ * 
+ * Represents a #schanid_t opaque object.
+ */
+
+/**
+ * gidispatch_rock_t:
+ * @num: Space for storing an integer.
+ * @ptr: Space for storing a pointer.
+ *
+ * You can store any value you want in this object; return it from your object
+ * registry and retained array registry callbacks, and the library will stash it
+ * away. You can retrieve it with gidispatch_get_objrock().
+ */ 
+
 /*---------- TYPES, FUNCTIONS AND CONSTANTS FROM GI_BLORB.H ------------------*/
  
 /**