Index


INTRODUCTION

Top

Metagen.pl scans the tagged C-source output of Glade, identifying delimeted module parts and converting them into meta-source content of Perl subroutines in a library module, from which the C-source can be regenerated after manual editing and augmentation of the meta-source. Augmentation of the meta-source is mainly to enable dynamic generation of source parts from loops supplying highly replicated GTK+ API calling sequences from external data sources such as directory listings or other databases, for the purposes of producing large GUI structures such as menus.

To maximize automation a module-partition-block sequential naming scheme is used, so that the computer can detect the proper sequencing of evolving module parts, and automatically assemble them into the generated C-modules. This enables the generation of the module assembly subroutines in the Perl module meta-source module, which would be called by the C-regeneration driver script.

Module Part Naming Scheme

    C-module-pseudonymserial-numeral[serial-letter]

In this naming scheme, each module part name has a prefix (the Glade-specific C-module pseudonyms: 'mainc', 'interfacec', 'interfaceh', 'callbacksc', 'callbacksh', 'supportc', and 'supporth'), and a suffix serial-code, consisting of a required serial numeral and an optional upper-case serial letter. In subseqent discussions of the tagging language this is referred to at the 'partname'.

Source-to-Metasource Abstraction

Module parts are of two kinds, static parts and dynamic parts, referring to what kind of meta-source they are translated into.

Static Parts

Static parts are transliterated from Glade output, either verbatim (as Perl 'text') or interpolated (as Perl "text").

Verbatim static parts are abstracted from the Glade-generated module text into meta-source as special Perl here-documents which preserve the source indentation scheme (unlike ordinary here documents).

Interpolated static parts are abstracted into here-doc meta-source equivalents, where each line has all non-identifier characters escaped by backslashes using the Perl quotemeta function.

Dynamic Parts

Dynamic parts are not translated from Glade-generated code, but are manually derived by using such code as "dummy examples". A large menu, for example, may not be practical to define using Glade, as it may require thousands of data items, such as a directory listing produced via a regular-expression script. The final code must contain a large number of GTK+ calls that look like some dummy examples that a tiny Glade menu would generate. So the pattern of GTK+ calls from the tiny menu can be used as replication patterns in dynamic meta-source script subroutines.

Looped Meta-Design Stubs

Looped meta-design (LMD) consists of three kinds of subroutine stubs and name-significant subroutines generated by metagen.pl: adaptable toploop stubs, adaptable subloop stubs. and append-subroutines:

adaptable toploop stubs

These are looping-element drivers that are repeatedly called by the external replication-data source (e.g. directory-list script) with each data item or item-set as arguments. The toploop is the root of a tree of subloop branches, where each branch incrementally builds (appends to) a separate dynamic part of the module. These separate dynamic parts are not contiguous, but have intervening static parts. The first dynamic part might contain declarations, the second might contain menu items, the third might contain signal connections, and the fourth might contain hooks. Typically, the name of a toploop stub will contain the partname of the first part generated (e.g.the declarations). To build the remaining branch parts, the adapted toploop stub will call the other subloop branch subroutines.

adaptable subloop stubs

These are looping-element branches that are called by the toploop subroutines to build (append to) specific dynamic parts of a module. As branches, their names are prefixed with the partname of the toploop stub, with a suffix of '_1', '_2', etc. signifying first branch, second branch, etc. Like the toploop stubs, these are subroutine wrappers for dummy example code generated by Glade, which are wrapped in Perl comments (with a leading # character) inside each stub. Thus the code position of the stubs corresponds to the dummy code position, namely the spot in the C-function where the new dynamically generated code, replacing the dummy code, must be positioned.

append subroutines

These are fully generated subroutines to be called by adapted toploop and subloop subroutines to build (append-to) the specific partnamed strings that will be inserted at the positions in the overall module where the toploop and subloop subroutines appear. But since the subloop names (as branches) are suffix-tagged versions of the corresponding toploop name, their names do not convey thier module position, enabling their output code to be automatically inserted in the proper position (i.e. their names are not partnames in a true sense, unlike the toprule name). Instead, the names of the append subroutines must define the partname (string name) of the text string comprising the module part. Thus each append subroutine is named 'append_<partname>, and <partname> must serially follow the partname that precedes it (the part that precedes the toploop or subloop stub) that calls it. This enables metagen.pl to automatically assemble the build subroutine that generates the complete module, as shown in the example below.

module build subroutine

The final step of module translation is the creation of the build_module subroutine, of which the following is an example:

                                                        
sub build_interfacec {
   my $interfacec = "// module interfacec\n";
   $interfacec .= load_interfacec0();	# == First part of interface.c
   $interfacec .= load_interfacec1();	# == create_GAEDWIN_decl_head
   $interfacec .= load_interfacec2();	# == pending_static_decl
   $interfacec .= $interfacec3A ;	# == pending menu declarations           (from sub append_interfacec3A)
   $interfacec .= load_interfacec4();	# == create_GAEDWIN_decl_all_action  
   $interfacec .= $interfacec5A ;	# == all-action menu declarations        (from sub append_interfacec5A)
   $interfacec .= load_interfacec6();	# == create_GAEDWIN_decl_tail
   $interfacec .= load_interfacec7();	# == window_start
   $interfacec .= load_interfacec8();	# == editor_frame
   $interfacec .= load_interfacec9();	# == mutation_block
   $interfacec .= load_interfacec10 ();	# == pending_static_block
   $interfacec .= $interfacec10A ;	# == pending menu items loop subroutine  (from sub append_interfacec10A)
   $interfacec .= load_interfacec11();	# == all_action_static_block
   $interfacec .= $interfacec11A ;	# == all-action menu items               (from sub append_interfacec11A)
   $interfacec .= load_interfacec12();	# == center_blocks_wrapup
   $interfacec .= load_interfacec13();	# == static_upper_element_signals
   $interfacec .= load_interfacec14();	# == static_pending_element_signals
   $interfacec .= $interfacec14A ;	# == pending menu signal connections
   $interfacec .= load_interfacec15();	# == static_all_action_signals
   $interfacec .= $interfacec15A ;	# == all-action menu signal connections  (from sub append_interfacec15A)
   $interfacec .= load_interfacec16();	# == button_signals                    
   $interfacec .= load_interfacec17();	# == window_start_hookups
   $interfacec .= load_interfacec18();	# == _editor_frame_hookups
   $interfacec .= load_interfacec19();	# == mutation_block_hookups
   $interfacec .= load_interfacec20();	# == pending_static_block_hookups
   $interfacec .= $interfacec20A ;	# == pending menu hooks                  (from sub append_interfacec20A)
   $interfacec .= load_interfacec21();	# == static_all_action_block_hookups
   $interfacec .= $interfacec21A ;	# == all-action menu hooks               (from sub append_interfacec21A)
   $interfacec .= load_interfacec22();	# == center_blocks_wrapup_hookups
   &PutFile("/home/bear/GAEMY/GUIbuild/interface.c",$interfacec);
} # ----- end build_interfacec

This build_interfacec subroutine is part of an actual Perl meta-source module "GAED_gen.pm generated by metagen.pl during the evolution of the GAEMY GUI interface, of which it is a part. It was converted to an HTML file for illustrative use in this document.

As illustrated, the $interfacec string, which contains the contents for the C-module "interface.c" is composed of 22 parts, of which 14 are static parts, loaded from here-docs by subroutines labeled 'load_partname', and 8 are dynamics parts, whose strings ($interfacec3A, $interfacec5A, $interfacec10A, $interfacec11A, $interfacec14A, $interfacec15A, $interfacec20A, and $interfacec21A) were generated by the corresponding append subroutines (as noted by the parenthesized comments on the right hand side).

The final statement of this build subroutine writes out the assembled $interfacec string, to create the interface.c module into the specified target build subdirectory from which a make process will create the final GUI executable.

Tagging Language

The tagging language is a set of precise keywords beginning with // denoting C-language single line comments. In the following description, bold is used for the keywords, monospace fonts are used for the module-name and attached N for numeral and optional [L] for letter. Italics are used to represent arbitrary and comments.

//BEGIN_module-nameN[L] comment

This tag and the following one delimit a block of source code to be abstracted into a Perl here-document subroutine as a verbatim meta-source module part. The name of the subroutine will be "load_module-nameN[L], and the comment will appear on the right-hand side of its heading. As the tag has the form of a C-comment, it is inserted as the first line of the module part.

//END_module-nameN[L] comment

This tag marks the end of a block of source code to be abstracted into a Perl subroutine. The tag itself is inserted as the last line of the module part.

//BEGIN_"module-nameN[L]comment

This tag and the preceding one delimit a block of source code to be abstracted into a Perl subroutine as an interpolated meta-source module part. The presence of the double quotes surrounding the partname, designates this as an interpolated part, meaning that perl variables appearing in the text (as $name or as ${name}) re interpolated when source is regenerated from meta-source. The tag itself is inserted as the last line of the module part

//TOPLOOP_module-nameN[L](args) comment

This tag and the following one delimit a block of "dummy example" source code (generated by Glade), which is to be replaced by a manually-adapted loop-element subroutine to be called from an external data-generation loop during source regeneration to produce a dynamic module part. The meta-source form that is generated by this tag-pair will be a Perl subroutine stub with perl-styled arguments $<(args)>. The remaining contents of this stub will be Perl comments containing the dummy example source text produced by Glade. The adaptive manual programming of this subroutine, left to be done in the EG_fixmeta phase, involves appending text patterns (like the dummy example text) to the next module-part by creating calls to the append subroutine for that part (defined in an immediately following APSUB_ tag (see below).

//ENDLOOP_module-nameN[L] comment

This tag marks the end of a block of unused source code to be copied into a toploop or subloop Perl subroutine stub as dummy-example source to guide the adaptive programming of a loop-element subroutine to append dynamically generated source.

//SUBLOOP_module-nameN[L](args) comment>

This tag and the preceding one delimit a block of "dummy example" source code (generated by Glade), which is to be replaced by a manually-adapted subloop-element subroutine to be called from a toploop subroutine, having the same module partname, during source regeneration to produce a dynamic module part. The meta-source form that is generated by this tag-pair will be a Perl subroutine stub with perl-styled arguments $<(args)>. The remaining contents of this stub will be Perl comments containing the dummy example source text produced by Glade. The adaptive manual programming of this subroutine, left to be done in the EG_fixmeta phase, involves appending text patterns (like the dummy example text) to the next module-part by creating calls to the append subroutine for that part (defined in an immediately following APSUB_ tag (see below).

//APSUB_module-nameN[L] comment

This is a singular tag which generates a Perl append subroutine, having the name append_partname, where partname is serially next after the module part preceding the last loop (toploop or subloop) subroutine. Thus the APSUB_ (APPlication Loop Element) tag is the third tag of a loop group, and must immediately follow the ENDLOOP_ tag of toploop or subloop tag pairs. The partname of the append subroutine thus reflects the serial location of the dynamic part in the module assembly. In this case, the generated dynamic part is a verbatim part.

//APSUB_"module-nameN[L]" comment

This form of the APSUB_ tag generates an append subroutine which interpolates text passed to it, translating perl variables having the form $name or ${name}. Thus in this case, the generated dynamic part is an interpolated part.