From ee81c9edf038fbd02460c512e64504bdf994d91e Mon Sep 17 00:00:00 2001 From: Philip Chimento Date: Fri, 9 Oct 2009 23:41:05 +0000 Subject: [PATCH] Documented the dispatch functions. Actually there will be two entries left 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 | 1 + docs/reference/.svnignore | 3 +- docs/reference/Makefile.am | 16 +- docs/reference/build-selector-table.pl.in | 32 ++ docs/reference/chimara-docs.sgml | 10 +- docs/reference/chimara-sections.txt | 40 ++ docs/reference/dispatch-selectors.sgml | 34 ++ docs/reference/dispatch.sgml | 39 ++ libchimara/dispatch.c | 132 +++++ libchimara/doc.c | 567 ++++++++++++++++++++++ 10 files changed, 869 insertions(+), 5 deletions(-) create mode 100644 docs/reference/build-selector-table.pl.in create mode 100644 docs/reference/dispatch-selectors.sgml create mode 100644 docs/reference/dispatch.sgml diff --git a/configure.ac b/configure.ac index 1c1d5e1..51a5cf2 100644 --- a/configure.ac +++ b/configure.ac @@ -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 diff --git a/docs/reference/.svnignore b/docs/reference/.svnignore index 7da551f..c35aef5 100644 --- a/docs/reference/.svnignore +++ b/docs/reference/.svnignore @@ -15,4 +15,5 @@ chimara-decl-list.txt chimara-overrides.txt chimara-undeclared.txt chimara-undocumented.txt - +selectors.xml +build-selector-table.pl diff --git a/docs/reference/Makefile.am b/docs/reference/Makefile.am index 6139eaf..f7f5ee5 100644 --- a/docs/reference/Makefile.am +++ b/docs/reference/Makefile.am @@ -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 index 0000000..80e8a48 --- /dev/null +++ b/docs/reference/build-selector-table.pl.in @@ -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 "\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 "\n"; + print " $1\n"; + my $functionname = $2; + my $linkname = '"' . $2 . '"'; + $linkname =~ s/_/-/g; + print " \n"; + print " $functionname()\n"; + print " \n"; + print "\n"; + } +} + +print "\n"; diff --git a/docs/reference/chimara-docs.sgml b/docs/reference/chimara-docs.sgml index 208c237..1f8cf2d 100644 --- a/docs/reference/chimara-docs.sgml +++ b/docs/reference/chimara-docs.sgml @@ -126,10 +126,16 @@ - + The Blorb Layer diff --git a/docs/reference/chimara-sections.txt b/docs/reference/chimara-sections.txt index 2281bfb..f933b2d 100644 --- a/docs/reference/chimara-sections.txt +++ b/docs/reference/chimara-sections.txt @@ -481,6 +481,46 @@ glk_cancel_hyperlink_event GLK_MODULE_HYPERLINKS +
+dispatch-interrogating +Interrogating the Interface +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 + +gidisp_Class_Window +gidisp_Class_Stream +gidisp_Class_Fileref +gidisp_Class_Schannel +
+ +
+dispatch-dispatching +Dispatching +gidispatch_call +gluniversal_t +
+ +
+dispatch-prototypes +Getting Argument Prototypes +gidispatch_prototype +
+ +
+dispatch-library-functions +Functions the Library Must Provide +gidispatch_set_object_registry +gidispatch_rock_t +gidispatch_get_objrock +gidispatch_set_retained_registry +
+
blorb-program What the Program Does diff --git a/docs/reference/dispatch-selectors.sgml b/docs/reference/dispatch-selectors.sgml new file mode 100644 index 0000000..6489324 --- /dev/null +++ b/docs/reference/dispatch-selectors.sgml @@ -0,0 +1,34 @@ + + +]> + + +Table of Selectors +3 +CHIMARA Library + + +Table of Selectors +Table of dispatch selectors for Glk functions + + +Description + +These values, and the values used for future Glk calls, are integers in the range 0x0001 to 0xFFFF (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. + +&selectors; + +Note that glk_main() does not have a selector, because it's provided by your program, not the library. + + +There is no way to use these selectors directly in the Glk API. + +An earlier version of Glk had gestalt selectors gestalt_FunctionNameToID and gestalt_FunctionIDToName, but these have been withdrawn. + +They are defined and used only in the dispatch layer. + + + diff --git a/docs/reference/dispatch.sgml b/docs/reference/dispatch.sgml new file mode 100644 index 0000000..7a811de --- /dev/null +++ b/docs/reference/dispatch.sgml @@ -0,0 +1,39 @@ + + + + +The Dispatch Layer +3 +CHIMARA Library + + +The Dispatch Layer +Calling Glk functions dynamically + + +Description + +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 — determining the capabilities and interfaces of Glk at run-time. + + +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. + + +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.) + + +How This Works + +The dispatch layer is implemented in a C source file, gi_dispa.c, and its header, gi_dispa.h. This code is platform-independent — it is identical in every library, just as the glk.h header file is identical in every library. Each library author should download the gi_dispa.c and gi_dispa.h files from the Glk web site, and compile them unchanged into the library. + + +This code is mostly external to Glk; it operates by calling the documented Glk API, not library internals. This is how gi_dispa.c 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; gi_dispa.c (and no one else) calls these functions. These functions are simple and should not make life much harder for library implementors. + + +The dispatch layer then provides a dispatch API. The heart of this is the gidispatch_call() function, which allows you to call any Glk function (specified by number) and pass in a list of arguments in a standardized way. You may also make use of gidispatch_prototype(), 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. + + + + diff --git a/libchimara/dispatch.c b/libchimara/dispatch.c index b1f84da..895d2e7 100644 --- a/libchimara/dispatch.c +++ b/libchimara/dispatch.c @@ -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. + * + * + * For example, it might keep a hash table for each opaque object class, + * mapping integer identifiers to object pointers. + * + * + * 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 + * N - 1N - + * 1, 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 that this is entirely separate from the regular Glk rock, which is + * always a #glui32 and can be set independently. + * + * + * 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. + * + * + * For example, MacGlk can open a stream when the user double-clicks a file; + * this occurs before glk_main(). + * + * + * 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. + * + * + * If you are keeping hash tables, for example, create them before you call + * gidispatch_set_object_registry(). + * + */ 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 + * owned 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 + * "#!" prefix. + * + * + * But not in every such case. Wait for the my_vm_reg_array() call to confirm + * it. + * + * + * 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. + * + * + * 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 "&+#!Cn". The latter two use + * arrays of #glui32, so the string is "&+#!Iu". + * + * + * 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)) { diff --git a/libchimara/doc.c b/libchimara/doc.c index c9c6e33..092eda2 100644 --- a/libchimara/doc.c +++ b/libchimara/doc.c @@ -840,6 +840,69 @@ * 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 — program, dispatch layer, Glk library + * — 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 allow the program to set them; it is the + * program's choice. The library does this by implementing + * set_registry functions — the functions to which the + * program passes its callbacks. + * + * + * Even though these callbacks and the functions to set them are declared in + * gi_dispa.h, they are not defined in + * gi_dispa.c. The dispatch layer merely coordinates + * them. The program defines the callback functions; the library calls them. + * + */ + /** * SECTION:blorb-program * @short_description: How to use the Blorb layer in your program @@ -2144,6 +2207,510 @@ * 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 Opaque Object + * Registry. + * + * 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 glk.h file. @index can range from 0 to + * N - 1N - + * 1, 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 + * N - 1N - + * 1, 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 glk_ prefix. + * + * The @id field is a selector — a numeric constant used to refer to the + * function in question. @name is the function name, as it is given in the + * glk.h file, but without the + * glk_ prefix. And @fnptr is the address of the + * function itself. + * + * + * This is included because it might be useful, but it is not recommended. To + * call an arbitrary Glk function, you should use gidispatch_call(). + * + * + * See Table of Selectors for + * the selector definitions. See Dispatching 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 Table of Selectors. @arglist is + * the list of arguments, and @numargs is the length of the list. + * + * The arguments are all stored as #gluniversal_t objects. + * Basic Types + * Numeric arguments are passed in the obvious way — 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 — #chars 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 void*, in order to + * handle all opaque pointer types.) + * + * However, pointers (other than C strings), arrays, and structures complicate + * life. So do return values. + * + * References + * A reference to a numeric type or object reference — that is, + * #glui32*, #winid_t*, and so on — takes + * one or two #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 + * 0xABCD: + * |[ + * 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. + * + * Structures + * 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 arglist[1..4] + * before calling gidispatch_call(). + * + * + * Theoretically, you would invoke #glk_select(%NULL) by setting' + * arglist[0].ptrflag 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. + * + * Arrays + * 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 one or three + * #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. + * + * + * glk_put_buffer() does not modify the array passed to it, so there is no + * need to copy the characters out. + * + * Return Values + * 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; + * ]| + * + */ + +/** + * 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: + * "4IuQa&Iu&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). + * "&Iu" is a reference to an unsigned + * integer, and "&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 + * (order does not matter): + * + * + * & + * 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. + * + * + * + * ! + * 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. + * + * + * + * + * 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 ------------------*/ /** -- 2.30.2