Reference

 gmBasic, Great Migrations Basic Reference Manual

The gmStudio orchestrates the execution of a number of Great Migrations tools to perform specific migration and development tasks. The most crucial of these tools is gmBasic.exe, which is a highly configurable VB6/ASP/COM compiler that produces .NET code as its output. This is a language reference manual for gmBasic. Its purpose is to describe the notations and conventions used by the tool to describe the languages -- VB6, ASP, and IDL --that it processes and the changes it makes in the content of the source codes to produce the desired .NET target code.

There are five different language types processed by gmBasic described in this manual:

Language Description
gmPL The Great Migrations Programming Language is a simple command language used to issue instructions to gmBasic and to enter declarations into the symbol table. It is not a procedural programming language, it is an xml-style scripting language.
gmSL The Great Migrations Scripting Language is a procedural language for use with the authoring and reporting facilities of gmBasic. It uses VB6-style syntax and is executed interpretively. It can also be embedded, using ASP-style syntax, into gmPL; thus, greatly enhancing the power and flexibility of that language.
gmNI The Great Migrations Native Interface makes writing native methods in C, C++, or C# possible to handle situations when a migration cannot be written entirely in the languages supported by the standard capabilities of the translation tool. Native code methods, loaded into runtime libraries, can handle events triggered during the translation process. These native methods have direct access to all of the information being managed during the translation via an extensive set of service classes.
gmIL The Great Migrations Intermediate Language is a binary reverse-polish representation. Source languages are compiled into gmIL. That representation is then analyzed and modified to be expressible in a target language. Then the gmIL is authored in that target language.
gmCL The Great Migrations Command Line controls the translation and deployment tools directly via a set of switches. There are many simple tasks that can be most easily performed by using the gmCL directly.

This manual uses TreeView, Copyright (c) 2006 by Conor O'Mahony, to control its navigation; and uses SyntaxHighlighter, Copyright (C) 2004-2009 Alex Gorbatchev, to make its code samples readable.

 Introduction to gmPL

The Great Migrations Programming Language -- gmPL -- is a simple command language used to issue instructions to gmBasic and to enter declarations and language descriptions into a symbol table. It is not a procedural programming language, it is an xml-style scripting language.

A gmPL source file is referred to as a script. Scripts are not only read and processed by gmBasic, they are also authored by gmBasic to describe what it has learned about the migration to date. The incremental quality improvement through an iterative process --i.e. translation tuning -- depends heavily upon the ability of gmBasic to author not only .NET code but also gmPL code. There are three types of scripts:

Script Description
Command Each invocation of the gmBasic tool is controlled by a command script entered on its command line. The primary purpose of the command script is to instruct gmBasic to do something; however, command scripts can also introduce declarations and language descriptions.
Reference All external components and environments that either control or are referenced by the translation process are described via reference files. These scripts primarily contain declarations but can also contain some instructions to manipulate the environment or other loaded descriptions. Most reference files are initially authored by gmBasic.
Imports External imports are tabulated during individual project translations and combined into an imports file so that they can later be authored. The imports scripts are cumulatively authored by gmBasic through a series of independent translations and are then finally used to author a .NET declaration framework.

The gmPL syntax uses an xml-style notation. gmPL files are valid XML files but the conventions they use are a subset of what can be done with XML. They are designed to be simple to read and simple to write. No individual statement syntax descriptions are needed or supplied.

Every statement begins with <statement where "statement" is a specified statement keyword. The statement keyword is optionally followed by a series of attribute="value" pairs where each "attribute" is one the specified attribute keywords defined for the statement.

Statement instances that do not introduce any substatements end in />. Statement instances that do introduce substatements end in > and are then followed by those substatements, and are finally ended by a statement of the form </statement>.

The "<statement" specification must occur on a new physical record in the file though it may be preceded by white space -- blanks and/or tabs. There can be no white space between the opening "<" and the "statement". White space and new lines may occur between the attribute-value pairs. Note that the Xml standard specifies that there be no white space before or after the equals sign in the attribute-value notation; however, this requirement is often ignored for readability, so blanks are allowed.

The gmPL statements are classified by type, and role.

The type of a statement specifies whether it can have other statements in its scope:

Type Description
Terminal Terminal statements can not have other statements within their scope. They must always be written using single statement syntax -- ending in />
Nonterminal Nonterminal statements can have substatements within their scope. They can be written using either single statement syntax or block syntax. It is valid to use block syntax with no intervening substatements.

The role of a statement specifies its primary purpose within the process:

Role Description
Command Command statements are the primary instructions issued to the tool and are used in practically all gmBasic command line scripts, though they are not limited to those scripts.
Utility Utility statements are like the command statements in that are specified within a command line script. Their role, however, is not to guide a translation but rather to perform a special operation that will eventually aid a translation.
Declaration Declaration statements describe the external components in the environment of a given translation. They are the primary commands in reference scripts, but are also used extensively in language descriptions.
Refactoring Refactoring statements make changes and/or add annotations to declared and source code defined symbols in order to change them to be compatible with the target language environment or to improve the quality of the translation.
Metalanguage Metalanguage statements define the intermediate language gmIL used to mediate between the source and target languages.


 gmBasic Command Statements

The details of the processing performed by gmBasic are controlled via an XML-based command line script. The command statements are the primary instructions used to produce translations as opposed to making and modifying declarations or performing auxiliary tasks.

The statement keyword for each command line script is usually gmBasic; however, it may be anything. The gmBasic statement itself has no attributes. Each of the command statements is a substatement of the gmBasic statement; however, several may be used in other contexts as well. These statements are as follows:

Statement Description of use
Analyse Controls the code analysis of a compiled code. Analysis is performed to change the intermediate code produced by the compiler into a form that can be authored in the target language.
Author Controls the actual authoring of the analysed intermediate code in the target language.
Compile Compiles a BASIC project or an ASP pageslice into an intermediate code unit. It also loads all information about externally referenced libraries and builds a table of all symbols encountered in either the source code or the external libraries.
Fix Supports making changes to the source code before it is compiled or target code before it is written.
If Specifies certain conditions for the inclusion or exclusion of the substatements within its scope.
Include Specifies the name of an external gmPL file whose statements are to be processed before processing the next statement in the including script.
LoadEnvironment Forces the loading of the environment that must be defined before any code can be processed.
LoadRuntime Loads a gmNI runtime Dll into the current execution space. This Dll may well be intermingled with Dlls loaded via refactoring and select statements.
Output Specifies where information being written should be sent and how it should be formatted.
Reference Alters the references information associated with a compilation unit.
Registry Enters various identifier pairs into storage for a variety of purposes. Registry statements are a primary vehicle used by gmBasic to communicate with itself during the translation tuning phase.
RunCommand Executes a method written using gmSL. This method may be predefined via the metalanguage. It may also be in a separate GlobalSettings file or it may be locally defined within the current script.
Select Specifies a wide range of attributes which control the behavior of gmBasic and which supply values for the properties of the gmSL Select class.
Storage Specifies how information gathered by the current script is to be stored in a virtual binary information file.


 Analyse Statement Summary

Analyse is a nonterminal, command statement that occurs only in command scripts. It initiates the code analysis phase of the translation process. This phase takes as input the intermediate code produced by the compiler and outputs an intermediate code that can be authored in the target language. Once completed each active code unit has two intermediate code representations stored in the virtual binary information file.

The attributes of the Analyse statement are as follows:

Attribute Description
Dialect This deprecated attribute specifies one of the three target language identifiers csh, vbn, or usr. It changes the system wide target language as selected and thus effects all further processing.
Project This attribute specifies the name of a previously compiled VBP project or ASP page. It restricts the analyzer to effect the specified component only. The use of this attribute should be limited to complex migrations where the order in which code units are processed must be controlled.

Though technically a nonterminal statement, the Analyse statement has no substatements at this time.

The script errors associated with the Analyse statement are as follows:

Error Description
1001 Encountered illegal ANALYSE directive %1d
1002 The Language dialect [%1d] is not supported.
1003 The Project [%1d] does not exist in storage area.
1004 The Component [%1d] is not a project.
1005 The Storage area does not contain any projects.

The analysis phase proceeds in the following steps. First, references to symbols with variant values are sought in the code to determine if their usage makes it possible to infer a stronger type for them. Most type inferences occur during this first step. Second, the code is reviewed and changes are made to make it compatible with the target .NET language. The actual changes made are different for C# versus VB.NET. Third, the argument passing logic is analysed. Argument types are cast to the appropriate types required by the parameters that they are passed to. Arguments that are passed ByRef are examined and where necessary temporaries are created to contain computed, constant, or NULL values that cannot be passed ByRef. Fourth, a final pass is made through the code units to make any final adjustments needed.

 Author Statement Summary

Author is a nonterminal, command statement that occurs only in command scripts. It takes as input the intermediate code produced by the analysis phase of the translation process. Using that code and the information contained in the symbol table it produces a fully functional code in the target language.

The attributes of the Author statement are as follows:

Attribute Description
Name This attribute specifies the overall name to be used as the web project name for an ASP site translation. If omitted, the name WebProject is used. This attribute is ignored in VB6 translations.
Project This attribute specifies the name of a previously compiled and analysed VBP project or ASP page. It restricts the author to that component only. If omitted, all active components are authored. Note if this attribute is an Xml script file, then the AuthorImports author is called just as it would be, had it been entered on the command-line. See the discussion of Imports scripts.

The substatements of the Author statement are as follows:

Substatement Description
Fix Adding a Fix command to the Author statement makes it possible to apply search and replace type edits to the translated source code before it is written. This facility has several benefits: first a quick, inexpensive way to solve one-off problems; and second, a temporary workaround to document and handle issues until a permanent solution can be incorporated into the standard tool configuration or the core translation engine.

The script errors associated with the Author statement are as follows:

Error Description
1007 Encountered illegal AUTHOR directive %1d
1008 The Project [%1d] does not exist in the storage area.
1009 The Component [%1d] is not a project.
1010 The Storage area does not contain any projects.

The actual records written by the author are stored in the virtual binary information file in editable text buffers. These buffers can then be modified via Fix substatements. It is the final records in these buffers that are actually written.

In addition to the target code the author also produces the project files needed to create .NET assemblies, resource files containing control property values, stubs for any external components referenced, and a reference file describing the public symbols exposed by the code. When-ever possible the code produced by the author can be deployed to its deployment location and directly built using the .NET compilers.

 Compile Statement Summary

Compile is a nonterminal, command statement that occurs only in command scripts. It compiles a specified source code project or ASP file. Within the translation process, the first significant step beyond simply loading a source code is converting that source code into an intermediate representation that can be analysed, refactored, and authored. The intermediate representation itself contains two subcomponents -- a symbol table that describes the components being manipulated and intermediate gmIL code that describes the actual operations being performed.

Both VB6 projects and ASP sites can be compiled. The Project attribute compiles VB6 projects and the PageSlice attribute compiles ASP pages.

The attributes of the Compile statement are as follows:

Attribute Description
Echo This attribute has one of the values Pass1, Pass2, or All. It is used to override the echoing of source code input as specified via the Select statement for the current compilation only.
Include This deprecated attribute requests that a single include file within an ASP site be compiled.
Level This attribute has one of the values Project, Load, Pass1, Pass2, and All. This attribute requests that the compile phase end after completing the indicated step. The default is All. The other values are only used for debugging purposes.
Page This deprecated attribute requests that a single page file within an ASP site be compiled without loading any includes that it might reference.
PageSlice This attribute requests that the specified page file within an ASP site be compiled, treating it in the same manner as it would be treated by the server when it gets a request for a page. It builds a source representation starting with any ASA file and its includes and then loads the page inserting any other includes as it sees them. The result of this step is a single source representation that can be compiled.
Project This attribute requests that the indicated project file, vbp, along with all references it makes and any code files that it loads be compiled.
ResX The gmStudio has the capability needed to author into a separate file the resX information for controls that do not use the standard resX conventions to store their property values. This attribute specifies the name of this separate file. The compiler searches this file first for property values before it searches the project supplied resX files. At present this feature is used only to use ImageStream Resx data generated from MSComCtl.ImageLists that are being replaced by WinForms.ImageList.
Script This deprecated attribute requests that a single script file within an ASP site be compiled.

The substatements of the Compile statement are as follows:

Substatement Description
Exename This substatement changes the Exename32 associated with the project,
Fix Using the Fix command statement as a substatement of the compile restricts the range of application of the fixes to code files within the project or pageslice.
Refactor Using the Refactor refactoring statement as a substatement of the compile restricts the range of application of any refactoring to the symbols defined within the project or pageslice.
Reference Using the Reference command statement as a substatement of the compile restricts references to its components to the current project or pageslice.
Select Using the Select command statement as a substatement of the compile is no different that using it outside of the compile. It is included as a substatement for convenience only.

The script errors associated with the Compile statement are as follows:

Error Description
1109 Encountered illegal COMPILE directive %1d
1110 Encountered illegal COMPILE directive %1d
1157 Unable to open project file [%1d]
1158 Unable to add project [%1d] to data storage area.

Before any code can be processed the environment within which that compilation is to occur must be established. For a given command script, the loading of this information occurs only once. The compiler checks if this load has occurred before it executes a Compile or Reference statement. In addition, the script can force the load to occur using LoadEnvironment statement. See the description of that statement for a details.

The compilation of VB6 project files consists of 4 distinct steps: first, the project file itself is loaded; second, all class, module, and form/usercontrol files are loaded; third, the individual source files are parsed and the symbols defined are organized into a symbol table; and fourth, the statements within the individual source files are converted into an intermediate representation.

Loading the project files begins by first storing the name of the project file in the symbol table and making certain that it is unique. Second, the project file itself is loaded into an edit buffer. Third, the GlobalSettings file is checked to see if any edit fixes are to be applied to the project file. Fourth, the file is searched for the its Name and Exename32 entries whose values are then stored in the symbol table.

Loading the individual source files involves searching the project file for Form, UserDocument, UserControl, Module, and Class entries whose values are the source code filenames to be loaded. Each file is then loaded into an edit buffer and its name is stored in the symbol table. For each file the GlobalSettings file is checked to see if any edit fixes are to be applied to it. In addition, the EditAspSource event is triggered, which could make additional changes to the file. Once all files have been loaded and individually edited, the subcommands associated with the statement are executed, up to any Refactor statements.

The initial parsing of the source files to organize the symbols defined into the symbol table is referred to as Pass1 of the compiler. If source code errors are encountered during this pass, then further processing within the compiler is blocked. If there were no problems, the final step is to tabulate all of the global symbols found so that they can be quickly identified by the next pass of the compiler.

The converting of the actual statements in the source files into intermediate gmIL code is referred to as Pass2 of the compiler. The first step is to process any Refactor substatements that remain. The quality of translations can often be greatly improved if symbols are strongly typed before the compiler processes the statements that reference them. Next if any Resource files are specified via the ResX attribute, they are loaded. Finally, the actual compilation into intermediate code is performed. There may well be syntax errors and warnings generated by this compilation; however, unlike pass1 errors these do not block further processing. Error causing source code statements are simply entered into the target translations as though they had been commented out in the source.

 Exename Compile Substatement Summary

Exename is a terminal substatement of the Compile statement. It changes the value of the Exename32 attribute in the project file before the first compiler pass has begun. If used, this substatement must precede any Refactor subcommands within the same specification. Note that an existing Exename32 is replaced by the new name; therefore, if there is no existing name, this substatement does nothing.

The attributes of the Exename substatement are as follows:

Attribute Description
id This attribute specifies the new Exename32 to be assigned to the project.


 Fix Statement Summary

Fix is a nonterminal, command statement that occurs in command scripts and can also occur within Compile or Author statements. It is used as well with EditFile commands in GlobalSettings files. This statement supports making changes to the source code before it is compiled or target code before it is written. A source code fix does not change the original VB6 or ASP files; rather it changes the code in memory after it is read.

The attributes of the Fix statement are as follows:

Attribute Description
Status This optional attribute describes the status of the fix. The process of fixing codes often begins with a raw editing change which is then later replaced by either a refactoring upgrade or by a more generic specification for the compiler or analyzer. When this occurs the original raw fix specification can be assigned a status description which then leaves the specification as entered but which tells this statement to simply skip the entire specification. If status is specified and is not set to Active then the entire fix block is skipped.
Host This optional attribute contains the fully qualified identifier of the project or page containing the text buffers to be fixed. The Host attribute can either specify that all projects/pages be included in the fix operation or that only one project/page be included. If the identified component is not present then the Fix is simply skipped; else only the text buffers associated with the indicated host are processed. If this attribute is omitted, then all text buffers in the scope of the command are processed.
Type This attribute contains one of the entries ReplaceGlobal or ReplaceSingle. The default is ReplaceGlobal which means that any matches and associated changes should be done for every occurrence in the set of text buffers in scope. The entry ReplaceSingle means to do it only once.
Name This attribute names the overall fix specification. It is used to document the script itself and appears in any progress messages that are displayed.
Lang This attribute contains one of the entries: vbp, csproj, vbproj, vb7, vbn, csh, or all. The default is all. This attribute restricts the set of text buffers searched to those that are written in the indicated language. Note that vb7 refers to the combined VB6/ASP/VbScript source languages.
FileFilter This attribute contains the name of a source file. It is used to restrict the fixes to a particular file within the set of files encompassed by Host attribute. If it is not present or if it is not within the scope of the restricted host then the fix is skipped.

The substatements of the Fix statement are as follows:

Substatement Description
Type This deprecated substatement can be used to change the active value of the Type attribute. It uses the syntax <Type>type value</Type>
Name This deprecated substatement can be used to change the active value of the Name attribute. It uses the syntax <Name>name value</Name>
FileFilter This deprecated substatement can be used to change the active value of the FileFilter attribute. It uses the syntax <FileFilter>filefilter value</FileFilter>
ReplaceFile This substatement replaces an entire file in one or more of the text buffers.
Replace This substatement replaces or deletes specified strings or blocks of code within the text buffers.

The script errors associated with the Fix statement are as follows:

Error Description
1016 This Fix subcommand is not valid: %1d


 ReplaceFile Fix Substatement Summary

ReplaceFile is a terminal substatement of the Fix statement. It replaces the content of files within the active text buffers with the content of a specified text file.

The attributes of the ReplaceFile substatement are as follows:

Attribute Description
Target This attribute contains the full pathname of the file containing the replacement records.
Name This attribute can be used to change the active value of the Name attribute encompassing the process.
Lang This attribute can be used to change the active value of the Lang attribute encompassing the process.
Source This attribute contains a filename that cat statements within the active text buffers must match in order to trigger the replacement.

Text buffers contain multiple files each of which is started with a cat filename statement and ended with a terminal marker !)(!. The ReplaceFile substatement searches the active text buffers for cat statements whose filename matches the source attribute. For each one found, all records below the cat and above the !)(! are deleted. Then the records from the target file are inserted.

 Replace Fix Substatement Summary

Replace is a nonterminal substatement of the Fix statement. It replaces or deletes either string fragments within text records or blocks of one or more records. When the fix type is ReplaceGlobal, then all matches in all active text buffers are processed. When the fix type is ReplaceSingle, once a match is found the process stops.

The attributes of the Replace substatement are as follows:

Attribute Description
Status This attribute can be used to change the active value of the Status attribute encompassing the process.
Name This attribute can be used to change the active value of the Name attribute encompassing the process.
Lang This attribute can be used to change the active value of the Lang attribute encompassing the process.

The substatements of the Replace substatement are as follows:

Substatement Description
OldBlock This substatement specifies the text that has to be matched to trigger a deletion or text substitution.
NewBlock This optional substatement specifies the substitution text to be used if a match is achieved using the OldText. If this substatement is omitted, then a match on the OldBlock deletes that text.

The script errors associated with the Replace substatement are as follows:

Error Description
1013 Replace missing initial OldBlock command, encountered: %1d
1014 Replace missing NewBlock command, encountered: %1d
1015 Replace missing End Tag, encountered: %1d

There are two forms that can be used for specifying the text blocks. The single line form is

    <OldBlock><![CDATA[...oldtext...]]></OldBlock>
         or
    <NewBlock><![CDATA[...newtext...]]></NewBlock>
The multi line form is
    <OldBlock><![CDATA[
    ...oldline 1...
        ...
     ...oldline n...

    ]]></OldBlock>
       or
    <NewBlock><![CDATA[
     ...newline 1...
        ...
     ...newline n...

    ]]></OldBlock>
 <NewBlock><![CDATA[
There is no requirement that the two forms match in a given replace. In all cases leading and trailing whitespace is ignored and the comparisons are not case-sensitive. Single line matchs replace or delete substrings within lines and may work on multiple matching substrings on the same line. Multiple line matchs work on entire lines.

 If Statement Summary

If is a nonterminal command statement that occurs only in command scripts. The statement adds conditional control to these scripts. It is common practice to use a single job script template for all the jobs in a migration set rather than separate scripts for each job. However, there are also common needs for slight variations in the translation configuration for different jobs. The If statement specifies certain conditions for the inclusion of command statements.

The attributes of the If statement are as follows:

Attribute Description
Id The statements within the scope of the If are processed only if the Identifier of the current storage area matches the specified value; otherwise the statements within the If are skipped.
Host The statements within the scope of the If are processed only if the host name is present in the storage area; otherwise the statements within the If are skipped.
Lang The statements within the scope of the If are processed only if the target language of the current script matches the specified value.

If multiple attributes are specified, then the conditions specified by each is checked as though the attributes where combined via an inclusive or.

The If statement has no substatements as such. Any command script statements may occur within the statement. An example would be something like this

   <If host="ListViewMigA" >
      <Refactor>
          <Reauthor subprogram="ListViewMigA.frmListViewMigA.Form_Load"     ...
          <Reauthor subprogram="ListViewMigA.frmListViewMigA.LV1_ItemClick" ...
      </Refactor>
   </If>
The If statement allows for general script templates to apply to more jobs in a migration set. It also helps eliminate "log noise" from things like skipping fixes, warning from refactoring commands, etc.

 Include Statement Summary

Include is a terminal command statement that can occur at any time in any gmPL source file except within a text block or a gmSL script block. It specifies the name of an external gmPL file whose statements are to be processed before processing the next statement in the including file. Include nesting may be up to 5 levels deep.

The attributes of the Include statement are as follows:

Attribute Description
Filename This attribute contains the full pathname of the gmPL source file to be included. If it is a simple local filename then it is assumed to be in the current directory as opposed to the directory containing the including file.

The script errors associated with the Include statement are as follows:

Error Description
1144 Unable to open Xml file: %1d


 LoadEnviroment Statement Summary

LoadEnviroment is a terminal, command statement that can occur only in command scripts. Before any code can be processed the environment within which that compilation is to occur must be established. For a given command script the loading of this information occurs only once. The compiler checks if this load has occurred before it executes a Compile or Reference statement. This statement can force the load to occur immediately in case it is needed for some special context.

The LoadEnviroment statement has no attributes.

The environment is described via three optional files: an Environment file, a TypeInference file, and a GlobalSettings file.

The Environment file is a reference script. It is normally created once by the user and contains settings that should always be used for a given code base. It is called Environment.%id%.xml and typically contains Select and Registry commands. It may be placed in any one of the search locations, but is normally placed in the target location.

The TypeInferences file is reference script. It is normally authored by gmBasic to report the type inferences that it has made while processing a code base. The purpose in creating this file is to give subsequent compilations knowledge about the ultimate types of the symbols that are weakly typed in the source code. This knowledge can then improve the quality of the translations. It is called TypeInference.%id%.xml and as authored by gmBasic contains only FixType Registry statements. It may be placed in any one of the search locations, but as authored it is sent to the Local location.

The GlobalSettings file is a pre compiled virtual binary information file built using a command script. It may contain any kind of information, though present applications only use Reference, Registry, and gmSL statements within the scripts that create GlobalSettings files. The full pathname is specified via a GlobalSettings="filename" Select attribute. Many entries in the GlobalSettings file are authored either by gmBasic or by the user via gmNI event handlers. It is discussed further under the description of the Registry statement.

 LoadRuntime Statement Summary

LoadRuntime is a terminal, command statement that can occur only in command scripts. It loads a runtime Dll into the current execution space of gmBasic. This Dll may well be intermingled with Dlls loaded via the Select RuntimeDll attribute and Dlls loaded via refactoring commands. There is a maximum of 64 Dlls that may be loaded. Each DLL exports certain methods, event handlers, that are then looked for by the execution logic of gmBasic when certain things happen or when certain points in the processing are reached.

The attributes of the LoadRuntime statement are as follows:

Attribute Description
DllName This attribute specifies a simple local file name of the runtime Dll to be loaded. It is looked for using the standard search order. That order is target location, local location, system location, and language location.
Filename This attribute specifies the full pathname of the runtime Dll to be loaded. It is used only if the DllName attribute is omitted.
Event If the DLL being loaded implements a CodeEvent event handler then this attribute specifies the identifier of this event. This event is triggered by references in the code to subcomponents that have a migUserCode value attributed to them. This is normally done with the Migrate command within a Refactor specification. Note that the event code compares only the first token of the code event string against the event identifiers of the currently active migration handlers.

The script errors associated with the LoadRuntime statement are as follows:

Error Description
1153 The RuntimeDll [%1d] could not be loaded


 Output Statement Summary

Output is a terminal, command statement that can occur only in command scripts. The statement specifies where information being output should be written and how it should be formatted.

The attributes of the Output statement are as follows:

Attribute Description
Filename This attribute contains the full pathname of the text file that is to receive the output to be produced. If this attribute is omitted, the standard output file is used.
Status This attribute specifies the status of the file: New means create a new file; Old means open an existing file and append the coming output at its end; and Close means simply close the current file. If omitted, then New is assumed.
Syntax Besides authoring record-oriented translations, gmBasic can also be used to write tabular reports based on the information collected while it was processing the source codes. This attribute specifies the output style to be used when producing these tabular reports. They can be produced in one of three styles: Tabbed simple tab delimited; Text text tabular; or Html html tabular. The default style is Text.
Striptrail This flag attribute, if On, requests that any trailing blanks be stripped from output records. This attribute is rarely needed.

The output produced by the Author statement, though controlled by an Output statement which must precede it, is actually first sent to a text buffer where it can be edited via Fix statements. It is the records within this text buffer that are then ultimately written to the Filename specified here.

The script errors associated with the Output statement are as follows:

Error Description
1139 The Output style keyword [%1d] is not accepted.
1140 The Output status keyword [%1d] is not accepted.


 Reference Statement Summary

Reference is a terminal, command statement that occurs not only in command scripts, but also as a substatement of the Compile statement and the Refactor statement. It explicitly loads a reference file into the current storage area. The typical reason for using this statement with VB6 project translations is that the project file does not explicitly list an external library whose members are in fact being referenced in the source code. In the case of ASP web translations, the external references are not explicitly defined; therefore, they must be supplied in the translation script using Reference statements.

The attributes of the Reference statement are as follows:

Attribute Description
Id This attribute simply identifies the external library to be loaded via its local filename like mso.dll or msword9.olb or mscomctl.ocx or msado20.tlb. The reference is then loaded using the same conventions as those used when loading an external referenced within a VBP project file.
Location This attribute specifies the full pathname of an external library as opposed to its simple local name. The file is loaded directly without going through the normal search logic and without first ensuring that it has not yet already been loaded. This attribute should only be used in special utility contexts. Note that when using this attribute the Id attribute, which is used internally to identify the external must be specified as well.
Registry This flag attribute, when specified as Off, requests that the normal Libname registry search not be performed on the specified Id.

The loading of references via the Id attribute proceeds in exactly the same manner as if they were loaded via a VBP file. First, before any code can be compiled or external reference loaded the environment within which the compilation is to occur must be established. See the description of the LoadEnvironment statement for details. Second, the registry is checked for a Libname entry. This entry is used to change the id under which a given external reference is processed. Third, a check is made to see if an external with the specified id has already been loaded. If so, it is not loaded again. Fourth, the extension xml is added to the back of the id to form a reference script filename and the file is looked for using the standard search order. That order is target location, local location, system location, and language location. Fifth, if located, the reference script is loaded. Sixth, the reference script filename is modified to be preceded by Mig. to form the name of a possible refactoring file which would contain statements modifying the characteristics of the components in the external. If located, this file is loaded as well.

 Registry Statement Summary

Registry is either a terminal or nonterminal command statement that occurs in both command and reference scripts. The registry is a directory which stores named settings and options for a variety of special uses within gmBasic or within user specified runtime Dlls. It contains a simple hierarchical set of name-value pairs stored under a type identifier. The values are either simple strings or a text buffer.

The attributes of the Registry statement are as follows:

Attribute Description
Type This attribute contains the identifier of the "special use" of the name-value pair being entered. If it is omitted, then the value LibName is supplied. Though gmBasic, itself uses a set of these types which are reserved, any other identifiers may be used. They are simple identifiers beginning with a letter and containing only letters and numbers. They are not case-sensitive.
Source This attribute contains the source name of the pair to which a target value is to be assigned. It may have any content. If a given pair is intended to be unique within a given type, then its name must be unique within that type only. They are not case-sensitive.
Target This attribute is used only with the terminal form of the statement. It contains the target value of the pair. It may have any content and need not be unique. At any given time a given source with a given type can have only one target. If the target attribute is missing or empty then the name value pair is treated as though it no longer exists within its location.

For the nonterminal form of the Registry statement the records in the scope of the statement are entered into a text buffer in raw form and that buffer is then associated with the source name. Any gmSL processing which these raw statements might undergo is performed when they are used not here where they are simply stored.

The current, globalsettings, and language storage areas all contain registries. Which registry is searched for a given type depends upon the type. They are as follows.

 Dependency: Specify a possibly omitted include file dependency

Dependency is a terminal registry type that is stored in the current storage area. Many ASP sites suffer from what is called "Omitted Include Syndrome". That is they contain code that depends on other includes, but not all of these needed includes are in the scope of every pageslice. This is particularly troublesome when the omitted includes contain variable declarations or scripted classes. The registry Dependency type is used to deal with this syndrome.

The attributes of the Dependency type are as follows:

Attribute Description
Source Pathname of include with a dependency
Target Pathname of include depended upon

The tool processes this registry type as follows:

  1. Before loading a reference to an include, determine if that include has a Dependency target entry. If the target include has already been loaded into the application being loaded, do nothing.
  2. If the target has not yet been loaded, load the target as if there had been an #include of target above the reference to source in the active pageslice.
  3. If target is also a source in another registry dependency type recursively process that dependency as well.
  4. If source is already loaded do not load it again. This is needed because a target include may well follow the source -- i.e. not actually be an omitted include file -- in an include sequence and will thus already have been loaded by this algorithm.
Since the algorithm does not require that dependent includes precede their sources, it is not expected to cycle. However, sites with cyclic include references do exist which may well be complicated by the aggressive use of this facility -- so user beware.

 EditFile: Supply a set of Fix statements for a specified file

EditFile is a nonterminal registry type that is stored in the globalsettings storage area. Very large code sites consisting of many, often shared, code files that require fixes need a way to organize these fixes. The simple use of general script templates to apply to all jobs in a migration set requires that each command script processed by gmBasic include all fixes for all jobs. In these template script files Fix statements are skipped if their host is not defined in the job at hand. In processing these, the search for the host has to be performed and the actual statements being skipped have to be checked for the termination record. These are trivial operations for small sites, but can quickly build up for large sites.

The EditFile source attribute specifies the full pathname of the file to be edited. The actual Fix statements then form the target text buffer.

<Registry type="EditFile" source="Pathname of file to be fixed" >
   <Fix>
      fix statements
   </Fix>
</Registry>
When a source file is initially loaded, be it a code file, or a VBP project file, or a web file, the globalsettings registry is checked for an EditFile on its full pathname. If present, the fixes are applied to the file using the standard facilities of the Fix statement.

The other advantage of using EditFile as opposed to the Compile Fix statement is that it is file specific not compilation set specific. Compile fix, for example, cannot edit the project file directly in its raw form as EditFile can. In the case of web files they are first converted into compilable form before they are presented to the compiler for processing. This form is close to the form of the raw web page, but it is sometimes difficult to construct the fix specifications correctly. EditFile simply sees the web file when it is loaded before any other processing occurs.

 FixType: Fix the type of a source component

FixType is a terminal registry type that is stored in the current storage area. It is used to fix the types of source code symbols when they are first encountered. gmBasic uses FixType registry statements when it authors the TypeInference reference script; however, they can also easily be entered into command scripts or be authored via gmNI.

The attributes of the FixType type are as follows:

Attribute Description
Source The possibly qualified identifier of a source code symbol whose type is the be fixed. Each time a new symbol reference is encountered gmBasic forms its fully qualified identifier, namespace.class.member.[..]. This identifier is then checked for a FixType target. If not found, the namespace component is removed from the fully qualified identifier, and that is checked for a target, and so on. Thus, depending upon how this attribute is written it can fix the type of only one symbol or of many symbols that have the same name.
Target The type to be applied to symbols whose identifiers match the source. This is either an identifier of one of the built in types or it is the qualified identifier of a user or external type.

The checks for the FixType registry entries are made during pass1 of the compiler when it encounters the definition of a variable or subprogram that is specified as VARIANT or OBJECT. They are also made by the pass2 compiler when it encounters the reference to an undeclared variable,

 FixStatus: Specify an ASP page status

FixStatus is a terminal registry type that is stored in the current storage area. It is used to change the translation status of a web page to UserControl as opposed to a code class or a regular aspx page.

The attributes of the FixStatus type are as follows:

Attribute Description
Source The full pathname of the asp page whose status is to change.
Target An identifier for the status desired. At this time the only entry is UserControl which means to translate the page as a usercontrol.

The FixStatus entries are checked for at compile time, so they must precede the first compile statement that will load the file.

 Guid: Define the value of a GUID

Guid is a terminal registry type that is stored either in the current storage area or the language storage area. The user storage area is checked first. Entries of this type are checked for by the gmSL.Runtime.Guid() method, which has one string parameter GuidName. That method attempts to find a Guid type entry whose source matches its parameter. If found, the target value is the guid to be used. If not found a new guid is generated and used.

The attributes of the Guid type are as follows:

Attribute Description
Source The logical name of the guid being sought. At the present time authoring methods within gmBasic seek the following logical names: Project, ProjectType1, ProjectType2, Flavor, and Interfaces. All have default values registered in the language file. Users can add additional logical names as needed.
Target The actual GUID to be used for the logical name.

The default values for the logical names currently being used are

 <Registry type="guid" source="Project"      target="{7EE74E01-07B7-4C4F-B053-895BB67A3A51}" />
 <Registry type="guid" source="ProjectType1" target="{349C5851-65DF-11DA-9384-00065B846F21}" />
 <Registry type="guid" source="ProjectType2" target="{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}" />
 <Registry type="guid" source="Flavor"       target="{349C5851-65DF-11DA-9384-00065B846F21}" />
 <Registry type="guid" source="Interfaces"   target="{447E0939-9DC6-40F4-A30E-26DC252607D3}" />
To change them, simply add an equivalent statement to the command script that does the authoring. Such entries are often put in the environment files loaded by scripts.

 IdfStatus: Specify the Interface Description File status of an external

IdfStatus is a terminal registry type that is stored in the current storage area. Reference scripts describing an external component like a Dll, or an ocx, or an olb, or a tlb are referred to as IDFs -- "Interface Description Files". The IdfStatus specifies how references to these components are to be treated. There four possible target settings -- Build, Migrate, Interop and External. When the Buildfile Select is local or global then the default IdfStatus is Build and the tool will author external dependencies as stub files or stub projects respectively. When BuildFile is off then the default IdfStatus is Migrate and the tool will author external dependencies as an assembly reference. The Interop setting is an intermediate one which says that any Mig files associated with the reference should be ignored. The External status blocks the authoring of stubs completely.

This attribute overrides the default status of the reference. The attributes of the IdfStatus type are as follows:

Attribute Description
Source The identifier of the external component whose default status is to be overridden.
Target One of the status identifiers: Build, Migrate, Interop or External.

MigrationSupport has special status in the system. The registry entry

  <Registry type="IdfStatus" source="MigrationSupport.dll" target="External" />
or adding the attribute idfStatus="external" to the library command causes MigrationSupport.dll to behave as other libraries do.

 Include: Specify the path to an include file

Include is a terminal registry type is stored in the current storage area. When gmBasic loads include files from ASP pages it first forms the full name of the include based on the pathname of the including file. Once this has been formed, the registry is checked for an Include entry that can specify a different pathname.

The attributes of the Include type are as follows:

Attribute Description
Source The pathname of the include as it would be formed by combining it with the pathname of the including file.
Target The actual pathname to be used for the include.


 LibName: Specify a library name or file name

LibName is a terminal registry type that is stored in the current storage area. It is used to change the name of an external component from the way it is being referenced either in the project file or in the source code into the name of the component describing it in the migration. External libraries are ultimately identified via their filename like mso.dll or msword9.olb or mscomctl.ocx or msado20.tlb. There are, however, in the windows registries at the home sites often alternative ProgIds registered for these names. It is these ProgIds that are used in the codes. The first reason for using the this registry type is to reconvert the ProgIds back into the local filenames.

The second reason for using the LibName registry type is to supply the name of a migrated description of the component to the translation scripts. Thus, if mscomctl.ocx has a migrated description in a file GM.mscomctl.ocx, then this type is used to make the switch.

The third reason is that source code bases often reference different versions of what is logically the same external component. For example there might be references to both msado25.tlb and msado21.tlb. In the translations the two get mixed and as such their classes are viewed as being different. Also redundant migration instructions need to be constructed. A set of statements like

   <Registry type="libname" source="msado15.dll" target="msado26.tlb"/>
   <Registry type="libname" source="msado20.tlb" target="msado26.tlb"/>
   <Registry type="libname" source="msado21.tlb" target="msado26.tlb"/>
   <Registry type="libname" source="msado25.tlb" target="msado26.tlb"/>
   <Registry type="libname" source="msado27.tlb" target="msado26.tlb"/>
resolves these problems.

The attributes of the Libname type are as follows:

Attribute Description
Source The pathname or ProgId of the external as it appears in the source code or project file.
Target The actual library local filename to be used to load the reference script that describes the external.


 OverLoadArgument: Specify types for arguments to be overloaded

OverLoadArgument is a terminal registry type that is stored in the globalsettings area. It is used to specify that individual subprogram arguments be overloaded to accept a list of differ types.

The attributes of the OverLoadArgument type are as follows:

Attribute Description
Source This attribute contains the fully qualified name of the argument -- i.e. project_identifier.class_identifier.subprogram_identifier.argument_identifier -- that is to be overloaded.
Target This attribute contains a comma-delimited list of the types to be allowed for the overloaded argument.

The registry is checked for the OverLoadArgument entry for a subprogram argument, either in a source file or in a reference script. If a target entry is found in the registry, then the list of types is processed and stored within the symbol table entry for that argument.

 ProgId: Resolve a ProgId

ProgId is a terminal registry type that is stored in the current storage area. It is used to resolve the ProgId argument value passed to the VB6 CreateObject method. The VB6 CreateObject method

CreateObject(progid As string,[servername As string])

creates and returns a reference to an ActiveX object. The ProgId argument contains the application name and class name of the object to create. If the ProgId can be determined, gmBasic scans the ProgId entries in the registry for any substitutions.

The attributes of the ProgId type are as follows:

Attribute Description
Source The identifier of the ProgId as determined from the call to CreateObject.
Target The identifier to be substituted for the ProgId to resolve its reference.


 RefactorFile: Supply a set of Refactor statements for a specified file

RefactorFile is a nonterminal registry type that is stored in the globalsettings storage area. Very large code sites consisting of many, often shared, code files whose symbols require refactoring organize these statements. The simple use of general script templates to apply to all jobs in a migration set requires that each command script processed by gmBasic check all refactoring statements for all jobs. In processing these, the symbol search has to be performed for each. This is a trivial operation for small sites, but can quickly build up for large sites.

The RefactorFile source attribute specifies the full pathname of the file whose symbols are to be refactored. The actual Refactor statements then form the target text buffer.

<Registry type="RefactorFile" source="Pathname of file to be refactored" >
   <Refactor>
      refactor statements
   </Refactor>
</Registry>
The registry is checked once for a RefactorFile entry for each class, module, form, or ASP file after the symbols for that file have been loaded but before and code has been compiled. There is nothing special about the refactor statements themselves. They behave exactly the same as Refactor statements placed within a Compile statement for a code project containing the specified file. Thus, the entry
   <Registry type="RefactorFile" source="\code\vb6\CommonFunctions.cls" >
     <Refactor>
       <FixType identifier="SortCollection.aObject" type="Interfaces.Icbn_Compare" />
    </Refactor>
  </Registry>
in a selected global settings file is identical to the following in a translation script
   <Compile project="\code\vb6\VariousCommonFunctions.vbp" >
      <Refactor fileFilter="[\code\vb6\CommonFunctions.cls]">
          <FixType identifier="SortCollection.aObject" type="Interfaces.Icbn_Compare" />
      </Refactor>
  </Compile>
Note the need in the FileFilter attribute for the square brackets surrounding the filename. They are supplied for the registry filename which must not contain those the brackets.

 SharedFile: Specifies that a file is shared and should only be processed once

SharedFile is a terminal registry type that is stored in the globalsettings storage area. The statements themselves are authored by the SharedFile utility statement. It is used to identify those files that are used by more than one VB6 project and to identify which project should be the only one that processes it. The other projects then refer to the components in the shared file as though they were external library components.

The attributes of the SharedFile type are as follows:

Attribute Description
Source The full pathname of a code file that is shared by multiple code project.
Target The full pathname of a project file that is to be defining project for the shared file.

The SharedFile statement description contains a detailed discussion.

 UsesInterfaces: Specifies that a project file uses certain interfaces

UsesInterfaces is a terminal registry type is stored in the globalsettings storage area. It is used to resolve references between independent projects that do not correspond to the build order -- i.e., a reference by a project early in the build order to one later in the order. These can even become circular references. A circular reference occurs when two projects reference each other either directly or indirectly via intermediate references. Clearly no rearrangement of the build order can be made to resolve circular references. To make this workable under .NET a migration is needed that uses interfaces to describe those classes that are being referenced before they are defined. Codes that use these interfaces must now reference the interface classes and not the concrete classes; and codes that define classes that are to be used in interface form must define those interfaces.

For example, assume a small system consisting of two projects Project1 and Project2 is built in that order. The problem is that Project1 references a class2 in Project2 and Project2 references a class1 in Project1. To resolve this, gmBasic creates an interface for class2 that defines the public methods of that class in project2 and any references to class2 in Project1 are changed into references to the interface class as opposed to the concrete class. Now when gmBasic processes Project2 it makes certain that Project2 implements the interface class in the concrete code for that class.

The first problem is to determine what information is needed to perform the uses interfaces migration and how that information can be specified. The information needed is a list of projects that must use interfaces along with a list of which projects supply those interfaces. In the example described above then the list would be

  project1 usesInterfaces project2
  project2 usesInterfaces project1
Note that the list is in build order since some of the low level symbol referencing migrations are dependent on this order. The UsesInterfaces registry type is used to store the list.

The attributes of the UsesInterfaces type are as follows:

Attribute Description
Source This attribute contains the Exename32 name of the using project.
Target This attribute contains a comma-delimited list of the Exename32 names of the supplying projects.

The symbol table retains the order in which the registry commands are entered under a given type, so determining order of entry is simple. In the present case then the registry statements would be as follows.

  <Registry type="UsesInterfaces" source="Project1.dll"  target="Project2.dll" />
  <Registry type="UsesInterfaces" source="Project2.dll"  target="Project1.dll" />
If a given project must reference more that one other project via an interface, then the target entry may contain a comma-delimited list. This might look as follows.
  <Registry type="UsesInterfaces" source="Project2.dll"
            target="Project1.dll,Project3.dll,Project4.dll" />
The Exename32 attributes are used to reference projects, not their filenames. This is because within referencing projects the library name is needed. It is the Exename32 attribute that supplies this name. Though the worse case scenario is a circular reference, the approach here does not assume this. Rather as each project code is processed, if its Exename32 is one of the target UsesInterfaces entries then all global classes in that project are classified as supplying an interface and all classes referenced in library files whose library name is one of the source are classified as using an interface.

At this point in time the UsesInterfaces list must be constructed by hand. The BuildOrder report does detect ordering problems but that detection does not appear to have enough information at this time. The basic rule is that if a project references a class from an earlier project either as the type of a method or as the type of a parameter to a method or as an instantiation within a method, then an interface must be used.

 RunCommand Statement Summary

RunCommand is a terminal, command statement is occurs only in command scripts. The statement executes one of the gmSL textcode methods, a user overridden version of one of those methods, or a textcode method stored in the current storage area or in the GlobalSettings storage area.

The attributes of the RunCommand statement are as follows:

Attribute Description
Id This attribute is the optionally qualified name of the method to be executed. The namespace is gmSL. This is followed by the class name and finally the method name. The current storage area is searched first, then the GlobalSettings area if it exists, and finally the language storage area.
Prams This attribute is a semicolon delimited list of the argument values to be passed to the method.

The RunCommand statement, as are all gmPL statements, is first preprocessed to convert any embedded gmSL expressions into the final form of the statement. This fact often simplifies specifying the Prams attribute in a generalized way.

 Select Statement Summary

Select is a terminal, command statement that occurs in both command scripts and reference scripts. It is the most used statement in gmPL. It specifies a large number of attributes which control the behavior of the translation process at every phase. They are organized by type and role.

The Select statement attributes also form a Select static class of properties within the gmSL. Each property value can be gotten via its identifier but can not be set, as the Select statement is used to do the sets. The fully qualified name of these properties is gmSL.Select.%attribute%. The gmSL namespace name may be omitted as may the Select class name, if the name is unique through-out the gmSL namespace. Omitting the class name is not recommended and may well be deprecated. The discussion of gmSL gives details about the gmSL.Select class.

 Select Identifier Attributes

The Identifier attributes are relatively short names used to identify various parts of the system. When referenced within the gmSL these names are all string properties.

 The Name,ToolName Identifier Attribute

The 63-character Name attribute contains the name used to refer to the gmBasic tool. This name appears in the banner and may be used and/or changed as the user desires. It can also be referred to using the attribute name ToolName.

 The Version Identifier Attribute

The 31-character Version attribute contains the build version number of the gmBasic tool. It can be used in banners and/or translation headers to document the version used to produce some translation. It may be changed by the user, but this is not recommended.

 The Company Identifier Attribute

The 63-character Company attribute can contain any company/application specific string that identifies the Company/copyright in effect. It is initialized as the release identifier for the tool itself which is the string System Build(%date% %time%).

 The Id Identifier Attribute

The 31-character Id attribute is the translation scenario identifier. This identifier is always set to identify the particular set of translation conventions being used. It typically has short values like std or bld and is usually added to the names of all bundle and virtual files created.

The tool has associated with it an Xml startup script. This script must have the same name as the executable file, except for the xml extension, and must reside in the same directory as the executable for the tool. The purpose of these startup files is to control how the tool presents itself and to specify the exact locations of the files that determine the behavior of the tool. These files do not in themselves control what the tools do, only where the tools should look for detailed information. Since it is often desirable to have multiple configurations available each Startup file consists of a series of subsystems, which have an id and then an independent set of specifications. Different subsystems are activated by following the tool name with a slash and then the subsystem id. If no subsystem id is used then the first subsystem is activated -- usually called std. Though it can be changed, this property contains the subsystem startup identifier that is used. Once set it should not be changed.

The tool itself uses this property to distinguish versions of components like type-inference files and deployment locations.

 The RootSpace Identifier Attribute

The 63-character RootSpace attribute specifies a string to use as the root of all namespaces -- i.e., it simply precedes all namespace declarations. Its default value is the empty string. If its value is set and then needs to be reset to the empty string, the notation rootspace="off" should be used.

 The AppNameSpace Identifier Attribute

The 63-charater AppNameSpace attribute specifies an alternative name for use in translations or reports. It is not presently used explicitly by the tool or in any of the standard text codes. If its value is set and then to be reset to the empty string, the notation AppNameSpace="off" should be used.

 The DevEnv Identifier Attribute

The 63-character DevEnv attribute contains the name of the development environment to be used to build the translated code. Its current vales are as follows:

Value Description of use
VS2005 To request Visual Studio 2005
VS2008 To request Visual Studio 2008
VS2010 To request Visual Studio 2010

The actual use of this property is restricted to the authoring facilities of the tool so that its values and conventions can be easily controlled by tool users.

 Select Value Attributes

The value attributes supply values to control the translation process or to supply sizes to various components. When referenced within the gmSL these values are all integer properties.

 The Codesize Value Attribute

The integer Codesize attribute specifies the maximum size of the packed code storage area which receives the code emissions produced by the compiler. Its default setting is 200000 bytes. As the compiler adds code of some size to the back of this storage area it checks to make certain that there is sufficient room. If there is not it logs the message
EMROOM: pcnt = (%= bytesused %) lPackedCode = (%= CodeSize %) size = (%= size %)
and ends execution. This is not a recoverable condition. The resolution is to add a command to the translation script to increase the CodeSize and then to rerun the script.

 The Progress Value Attribute

The integer Progress attribute controls progress reporting while the tool is operating. Each level includes all messages from lower levels as well as those it introduces itself. Its values are as follows:

Value Description of use
0 Do not write progress messages
1 Do write progress messages
2 Describe text block replacements made while doing Fixes.
3 Include elapsed time messages for the various subsystems in the tool

In particular the following types of messages are written:

StateofTool Message issued
Asp Compile Compiling asp file: filename
Fix Editing Detailed messages describing what is being done
References Loading reference: location
Vb6 Compile Reprocessing file: filename
Resources Loading resource: from resource file
Vb6 Load Processing file: filename


 The Indent Value Attribute

The integer Indent attribute specifies the indentation width in the authored output. It should be set to a reasonably small positive value or zero. The default value is 3. When authoring gmBasic does not attempt to reproduce the leading white space in the source code; rather it keeps track of the margin nesting level via the p and q escape characters in the surface patterns or via the Author.IncreaseMargin() and Author.DecreaseMargin() method calls in gmSL scripts and then uses this margin level times the indentation width to determine the amount of leading blanks to add. Note that if this property is zero then gmBasic uses the margin level number of tab-characters to lead the line.

 The BlockMethods Value Attribute

The integer BlockMethods attribute specifies that subprogram codes should be blocked for readability. This value has two effects -- first, it adds blank lines between method declarations and second it shows blank lines within methods as empty comments to make them stand out. The default value is 0. The values are as follows:

Value Description of use
0 Do not do any additional formatting to block methods.
+n Block methods by adding n blank lines before the comments that introduce the method and change any blank lines within the method to empty comments.


 The MaxOutputWidth Value Attribute

The integer MaxOutputWidth attribute specifies the maximum length of lines authored in codes. By default it is set to 256. Note that setting this value too high could cause problems for the editor. An absolute maximum value of 2048 is suggested. For ASP translations, it is suggested that this property be set to at least 1000 if a lot of complex markup is involved. gmBasic is careful to break long statements at the appropriate token boundaries so as not to cause any syntax errors in the target codes.

 Select Enumerated Attributes

The enumerated attributes take attribute specific enumeration entry values to control the translation process. When referenced within the gmSL each attribute value can be referenced as enumeration.entry.

 The Echo Enumerated Attribute

The enumerated Echo attribute requests that source code be echoed as it is processed. It is defined via the EchoType enumeration whose entries are as follows:

Entry Description
off No not echo the source code during compilation
pass1 Echo the source code during the first pass of the compiler
pass2 Echo the source code during the second pass of the compiler
all Echo the source code during both passes of the compiler

To have any effect this attribute value must be set prior to the compile statements that are to echo their input. The default setting is off. Note that individual compile statements can locally override this attribute if they require special treatment.

 The Dialect Enumerated Attribute

The enumerated Dialect attribute specifies the target dialect to be used. It is defined via the DialectType enumeration whose entries are as follows:

Entry Description
vbp Specifies that target is a project or assembly file.
vb7 Specifies that the target language should be Version 7 Basic. This is the combined VB6, ASP, VbScript source language processed by gmBasic.
csh Specifies that the target language should be C#.
vbn Specifies that the target language should be VB.NET.
usr Specifies that the target language should reflect a user specified dialect as described in the language description.
gms Specifies that the target language should be gmSL.
jav Specifies that the target language should be Java.

The default setting is csh. The only target languages supported in the standard release of gmBasic are csh and vbn. Applications of gmBasic have targeted all of the above languages. The capabilities of the surface-pattern author as well as the other MetaLanguage specifications combined with the gmSL and the gmNI make supporting other target languages possible. It is important that the target dialect in a translation script be specified before the first compile statement. The target dialect effects all phases of the translation process including the compilation phase.

 The TypeInteger Enumerated Attribute

The enumerated TypeInteger attribute specifies whether BASIC integers should be treated as 2-byte integers or 4-byte integers. It is defined via the FixedType enumeration whose entries are as follows:

Entry Description
Short Treat BASIC integers as 2-byte integers in the target languages.
Integer Treat BASIC integers as 4-byte integers in the target languages.
Long Treat BASIC integers as 4-byte integers in the target languages.

The default setting is Integer. To date all applications of gmBasic have used this default setting and it should probably not be set to short unless the BASIC code is performing operations that require BASIC short arithmetic. If this the case, migration logic will probably be needed anyway.

 The TypeLong Enumerated Attribute

The enumerated TypeLong attribute specifies whether BASIC longs should be treated as 4-byte integers or 8-byte integers. It is defined via the FixedType enumeration whose entries are as follows:

Entry Description
Short Treat BASIC longs as 4-byte integers in the target languages.
Integer Treat BASIC longs as 4-byte integers in the target languages.
Long Treat BASIC longs as 8-byte integers in the target languages.

The default setting is Integer. To date all applications of gmBasic have used this default settings and it should probably not be set to long unless the BASIC code is performing operations that require that longs be larger than integers. If this the case, migration logic will probably be needed anyway.

 The ExceptionHandling Enumerated Attribute

The enumerated ExceptionHandling attribute specifies how the analyzer should deal with exception handling. It is defined via the ExceptionType enumeration whose entries are as follows:

Entry Description
Simple Indicates that logic to set the VBNET.Error object will not be authored.
setErrorObject Indicates that logic should be authored in try/catch blocks so that the VBNET.Err object will be set to reflect the error number.
useTryCatch Indicates that the tool should use Try-Catch as opposed to On Error GoTo style error handling for VBN translations. In essence, this switch tells the analyzer to use the same analyzer method that is presently used for CSH for VBN as well.

When the setErrorObject exception type is active the first statement of each catch block has a call to MigrationSupport.Lib.SetErrorObject included. Thus, for example, a simple block becomes

  catch(Exception exc)
  {
      MigrationSupport.Lib.SetErrorObject(exc);
  }

 The CheckDeclares Enumerated Attribute

The enumerated CheckDeclares attribute controls the checking and reporting of the consistency between DECLARE statements in the source codes and those in a interface description files. It is defined via the CheckType enumeration whose entries are as follows:

Entry Description
Off Does not use external descriptions to check declares.
On Checks the declares and warns about inconsistencies.
Ignore Checks the declares but ignores differences between source and external descriptions
Audit Reports on all Declares found in the source codes.

In particular this attribute is used by the pass1 compiler when it processes a DECLARE statement. Its first step is to attempt to find an interface description file for the library file that contains the method being declared. The standard search order -- target, local, system, language file -- is used. At the present time partial descriptions for the following libraries are available:

LibraryFileName Interface Description file
advapi32.dcl advapi32.dcl.xml
comdlg32.dcl comdlg32.dcl.xml
gdi32.dcl gdi32.dcl.xml
IpHlpAPI.dcl IpHlpAPI.dcl.xml
kernel32.dcl kernel32.dcl.xml
mpr.dcl mpr.dcl.xml
ole32.dcl ole32.dcl.xml
olepro32.dcl olepro32.dcl.xml
shell32.dcl shell32.dcl.xml
user32.dcl user32.dcl.xml
vb6control.dcl vb6control.dcl.xml
version.dcl version.dcl.xml

If there is no IDF or if the attribute is set to off, then gmBasic does no more checking and issues no messages. If the method is found and the attribute is set to audit then the following message is logged

NOTE: DECLARE (%= Ident %) with Alias (%= Alias %) in Library (%= library %) is being defined.
If the method is not found and the attribute is set to on then the following message is logged
WARNING#004: DECLARE <%= Ident %) with Alias (%= Alias %) in Library (%= Library %) is not defined.
Finally, if a method description is found and it the property is not set off, the tool checks the number of parameters, the return type, and the individual argument types and logs messages if it finds any differences.

 The MissingRef Enumerated Attribute

The enumerated MissingRef attribute describes the treatment of missing references either to project file references to external libraries or ASP page references to include files. It is defined via the MissingType enumeration whose entries are as follows:

Entry Description
Off Issue a warning message about the missing reference and continue processing.
Fatal Issue a message about the missing reference end execution.
JustDoIt Issue no message and continue processing as though the referenced library description file or include file had been found and loaded.


 The AuthorLibrary Enumerated Attribute

The enumerated AuthorLibrary attribute requests that interface description files be authored when libraries or control projects are translated. It is defined via the AuthorType enumeration whose entries are as follows:

Entry Description
off Requests that no interface description file be authored.
on Requests that an interface description file be authored to the code bundle. It is not sent to the local location until the bundle is deployed.
deploy Requests that the IDF be authored directly to the local location when the defining source code is translated.

Any interface description file authored is ultimately sent to the current local location.

 The LateBindings Enumerated Attribute

The enumerated LateBindings attribute specifies how late bindings should be treated by the compiler. It is defined via the ProcessingType enumeration whose entries are as follows:

Entry Description
Ignore Simply generate code to call the .NET Interaction.CallByName method which makes a runtime determination of what component to access or execute.
Warn Before generating the CallByName code send a warning message to the log file.
Error Before generating the CallByName code send an error message to the log file. Depending upon the setting of the SyntaxFatal attribute, this can end execution.

A late binding is a reference to a method or property of an object when the class of that object has not been resolved.

 The UndefinedVariables Enumerated Attribute

The enumerated UndefinedVariables attribute specifies how to handle variables that are referenced in the source code but are not declared. It is defined via the ProcessingType enumeration whose entries are as follows:

Entry Description
Ignore Simply add the variable to the symbol table and continue processing. and report nothing for undeclared variables.
Warn Add the variable to the symbol table and send a warning to the log file.
Error Before adding the variable to the symbol table, send an error message to the log file. Depending upon the setting of the SyntaxFatal attribute, this can end execution.


 The UndefinedProperties Enumerated Attribute

The enumerated UndefinedProperties attribute specifies how to handle properties that are referenced in designer code but not declared in the interface description file. It is defined via the ProcessingType enumeration whose entries are as follows:

Entry Description
Ignore Report nothing for undefined properties.
Warn Send a warning to the log file for undefined properties.
Error Send an error message to the log file for undefined properties. Depending upon the setting of the SyntaxFatal attribute, this can end execution.


 The BuildFile Enumerated Attribute

The enumerated BuildFile attribute specifies the external handling strategy for migration. The migration process proceeds as follows:
  1. The tool associates with each translation local stubs for the external references made by that translation. This then makes checking that the translation is correctly formed possible and gives an inventory of the external components referenced.
  2. Once the above has been performed for every code in a code set, the storage files produced are scanned as a group and a set of global library stub files are created that encompass the entire set of references made.
  3. The library stubs are build so they can be referenced. It is these stubs that get filled in and maintained by the migration team from this point forward.
  4. A new set of translations are then created which do not contain any stubs but that reference the libraries created above.
The discussion of the GlobalStubs utility statement describes the actual creation of the global library stubs. The BuildFile is concerned with controlling the production of the local stubs. It is defined via the BuildFileStatus enumeration whose entries are as follows:

Entry Description
Off This entry specifies that some other migration approach is being used. No stubs, local or global, are being used.
On This entry specifies that local stubs are being authored. It is deprecated.
Local This entry specifies that local stubs are being authored.
Global This entry specifies that global native stub files have been created and should be used. This will be the typical setting, once a code set migration is running beyond step 1 above.


 Select Search String Attributes

The search string attributes are used to specify search locations for reference scripts and runtime Dlls. When referenced within the gmSL these attributes are all string properties. Several of the search string attributes have alternative attributes used in gmStudio template files.

The search order is Target, Local, System, and Language.

 The Target Search String Attribute

The Target search string attribute specifies the location used to store the migrated versions of reference scripts needed for the target translations. It is also the location for user authored runtime Dlls. It is the first location searched by gmBasic when it is looking for an external reference description file or a runtime dll. This area should only be used for user files.

 The UserFolder Search String Attribute

The UserFolder search string attribute is a gmStudio template variable. When used within command scripts it specifies the Target location. This attribute should only be used within template files.

 The Local Search String Attribute

The Local search string attribute is the full path of the location used by gmBasic for its authored AuthorLibrary local description files and other intermediate output files. It is the second location searched by gmBasic when it is looking for an external reference description file or a runtime dll. This area should not be used for user files, because it is normally emptied before the start of each migration cycle.

 The IdfFromCodeFolder Search String Attribute

The IdfFromCodeFolder search string attribute is a gmStudio template variable. When used within command scripts it specifies the Local search location. This attribute should only be used within template files.

 The System Search String Attribute

The System search string attribute is the full path of the location used by gmBasic for its authored reference script, interface description files. These files are translations of IDL files describing COM components stored in the system and referenced by the source code being translated. The discussion of the gmCL has a description of IDL to reference script translation. It is the third location searched by gmBasic when it is looking for an external reference description file or a runtime dll. This area should not be used for user files, because it normally contains interface description files for the codes being translated in their original form. These are needed to facilitate translations during the early phases of the migration before all build order and circular reference problems have been resolved.

 The IdfFromIdlFolder Search String Attribute

The IdfFromIdlFolder search string attribute is a gmStudio template variable. When used within command scripts it specifies the System location. This attribute should only be used within template files.

 The Language Search String Attribute

The Language search string attribute is the full path of the location used by gmBasic to store the language file needed whenever gmBasic runs. Once the language file has been loaded, this location is changed to specify the storage area used to contain the default versions of reference scripts and runtime Dlls as installed. It is the fourth and final location searched by gmBasic when it is looking for an external reference description file or a runtime dll.

 Select Location String Attributes

The location string attributes are used to specify non search locations to be used by gmBasic. When referenced within the gmSL these attributes are all string properties. Several of the location string attributes have alternative attributes used in gmStudio template files.

 The VirtualRoot Location String Attribute

The VirtualRoot location string attribute is used with ASP pageslice translations. It contains the full path of the folder that should be used as the virtual root when resolving includes.

 The Library Location String Attribute

The Library location string attribute is the full path of a library storage area. In particular, this is the location of the cached Interop libraries. This attribute is used widely via the gmSL when Library declarations are processed. Both the Location and AxLocation attributes of that statement are authored by gmBasic to begin with %library%. The gmSL description has details about this use of select attributes in gmPL statements.

 The GenExternFolder Location String Attribute

The GenExternFolder location string attribute is a gmStudio template variable. When used within command scripts, it specifies the Library location. This attribute should only be used within template files.

 The Idl Location String Attribute

The Idl location string attribute specifies the location of library Idl files to be imported. When the Idl compiler executes an import statement it first searches the current directory for the file being imported and then searches the directory specified by this attribute. If the imported file cannot be located an error message is logged and execution is ended.

 The DeployLocation Location String Attribute

The DeployLocation location string attribute specifies the location to which generated projects are deployed. If omitted a location within the source project location is used. By default before copying a translated project code to a deployment location the previous content of that location is removed completely using the following deployment commands
  rmdir (%= DeployLocation %)
  mkdir (%= DeployLocation %)
  mkdir (%= DeployLocation %)\bin
Note that the deployment rmdir command does not require that the location already exists. Deployment commands are documented within the gmCL discussion.

When doing multiple project translations each project should be assigned its own unique deployment location.

 The NetProjFolder Location String Attribute

The NetProjFolder location string attribute is a gmStudio template variable. When used within command scripts, it specifies the DeployLocation location. This attribute should only be used within template files.

 The RuntimeDlls Location String Attribute

The RuntimeDlls location string attribute specifies a list of external Dll names which will be loaded by gmBasic before it begins its first compile. The LoadEnvironment statement discussion describes this operation. The RuntimeDlls select must precede the first Compile or Reference statement in the command script or it must be placed in the environment file itself.

 The GlobalSettings Location String Attribute

The GlobalSettings location string attribute specifies the full pathname of a pre compiled GlobalSettings file which will be loaded by gmBasic before it begins its first compile. The LoadEnvironment statement discussion describes this operation. The GlobalSettings select must precede the first Compile or Reference statement in the command script or it must be placed in the environment file itself. The GlobalSetting file is a storage area produced by a command script which can contain almost anything. At this point in time the primary entries are Registry statements, gmSL methods, and loaded references. Simply stated, this file contains all of the globally checked for "things" which alternatively are entered into template files. Its content is described in many places throughout this manual.

 Select ComputeConditional String Attribute

The ComputeConditional string attribute controls the conditional compilation approach taken by gmBasic. Its entries are as follows:

Entry Description
Off When ComputeConditional is Off, gmBasic treats conditional statements as though they were simply another statement in the language. They are compiled and their intermediate code is authored as though equivalent statements existed in the target language. This approach is workable when a few simple conditional statements exist in the code, but is unworkable when complicated conditional logic is being used.
Migrate When ComputeConditional is Migrate, gmBasic attempts to do a full migration to the .NET languages. To do this requires assuming that all conditional variables are boolean, where True corresponds to defined and False corresponds to undefined. Variables defined either via a CondComp specification in the project file or a #const specification in the source code, that are not True or False are set to True if they are nonzero and False if they are zero.
On When ComputeConditional is On, gmBasic traps all conditional value settings in project files and #const directives. The compiler, not the editor, then evaluates the actual conditional expressions using the standard expression processor and its internal engine that evaluates gmIL code. Based on this evaluation, source code records that should be included are included and source code records that should not be included are commented out. All code conditional statements themselves are also commented out.

The default entry is Off. When ComputeCondional is specified but not one of the above it is assumed to contain a CondComp style specification like

   <Select ComputeConditional="DEBUGMODE=0:WIN32_IE=0x400" />
         or
   <Select ComputeConditional="Win32=1:Win16=0" />
This specification is processed as though it have been entered in the project file and the entry is changed to On.

Within Visual Basic Compilation constants can be set within a module using #Const. The examples normally provided for this statement show simple integer values being assigned. More complicated value specifications are also allowed. To date the True and False reserved words have also been encountered as well as Hex constants.

On the .NET side Conditional Constants are simply defined or they are undefined. They can carry no values. It is this fact that makes the logic surrounding ComputeConditional a necessity as opposed to a simple optional approach. Various approaches using name_mangling have been tried, but all have fallen far short of dealing with the actual use of these constants in VB6. A typical VB6 program that uses Conditional Compilation at all aggressively will not build unless the ComputeConditional capability is turned on. It is also common to see conditional variables referenced but never assigned values in contradictory ways. It is this fact that makes the simple on setting unworkable in many instances.

 Select Author Flag Attributes

The Author Flag attributes are on/off flags that control conventions used within the Author. When referenced within the gmSL they are boolean properties with On being True and Off being False.

 The BlockComments Author Flag Attribute

The BlockComments author flag attribute requests that comments be blocked in the authored output -- i.e. be surrounded by blank lines, in the authored output. The values are as follows:

Value Description of use
Off Do not surround comments with extra blank lines.
On Block comments by surrounding them with an extra blank line.

The default value is Off.

Note that the writing of comment blocks and of subprogram declarations are interrelated. In particular if the block of comments is directly followed by a subprogram declaration then the BlockMethods spacing overrides the BlockComments spacing -- i.e. both are not applied.

 The DeleteUnused Author Flag Attribute

The DeleteUnused author flag attribute controls the removal of unused constants from the translations. Its values are as follows:

Value Description of use
Off Do not remove unused constants from the translations.
On Remove unused constants from the translations

The default value is Off.

 The SingleQuotes Author Flag Attribute

The SingleQuotes author flag attribute specifies that single quotes should be used when nested literal strings result from the migration of ASP codes. Its values are as follows:

Value Description of use
on Requests that single quotes are used.
off Requests that other nested literal string techniques are used such as inserting backslashes or double double quotes as is appropriate for the target language.

The default value is Off.

 The AuthorImports Author Flag Attribute

The AuthorImports author flag attribute controls the authoring of global imports in a multi-script context. When the tool is ready to process imported global references in the current translation script, if there is present an ImportsGlobal file then it must be read. Imports that are currently present must have their reference information updated and those that are not present must have their information copied to the scratch stream. Its values are as follows:

Value Description of use
On Any existing ImportsGlobal file is ignored and the property is set to Off.
Off Any existing ImportsGlobal file is read.

The default value is Off.

 The UseDeployedImports Author Flag Attribute

The UseDeployedImports author flag attribute controls the overall authoring of Imports. Its values are as follows:

Value Description of use
On Block the authoring of Imports
Off Do not block the authoring of imports.

The default value is Off.

 The CompilerWarnings Author Flag Attribute

The CompilerWarnings author flag attribute is used to control the authoring of TreatWarningsAsErrors entries in the project file. Its values are as follows:

Value Description of use
Off Set TreatWarningsAsErrors to "false"
On Set TreatWarningsAsErrors to "true".

The default value is Off.

 The OmitAppObjects Author Flag Attribute

The OmitAppObjects author flag attribute removes the AppObject declarations from the translations without effecting the reference logic to them in the compiler. Its values are as follows:

Value Description of use
Off Include AppObject declarations in the translations.
On Omit AppObject declarations from the translations.

The default value is Off.

 The useUserControls Author Flag Attribute

The useUserControls author flag attribute specifies that all ASP PageSlice includes should be authored as user controls. Its values are as follows:

Value Description of use
Off Do not author all PageSlice includes as user controls.
On Do author all PageSlice includes as user controls.

The default value is Off.

 The ShowVerticalLists Author Flag Attribute

The ShowVerticalLists author flag attribute controls how long statements that include array initializations are authored. Its values are as follows:

Value Description of use
Off Do not check for array initializations in long statements.
On When authoring a long statement that includes an array initialization, put each element of the array initialization on its own line.

The default value is Off.

A "long line" is any line whose length exceeds the value of the attribute MaxOutputWidth. Therefore, it is a line that must be broken anyway. The test for "includes an array initialization" is a text search for string []{. The algorithm is fairly general, but there may always be weird cases where it breaks down.

 The Migrate2 Author Flag Attribute

The Migrate2 author flag attribute controls the authoring of the long description comment that is usually associated with all resx files. Note that empty resource files are often created even when no resource data is present; however, gmBasic authors a resx file only if resource data is present. Its values are as follows:

Value Description of use
Off Author the descriptive comment with all resx files.
On Do not author the descriptive comment.

The default value is Off.

 The ProjectReference Author Flag Attribute

The ProjectReference author flag attribute controls how project files reference external dependencies. Its values are as follows:

Value Description of use
Off Dependencies are referenced as binary assemblies
On Dependencies are referenced via their source project

The default value is Off.

The implementation of the On behavior is complicated by the fact that the originally authored project file and the downstream reference to that project file must have matching GUIDS specified. To understand this attribute and its On implementation, consider a simple project, that authors a library and an interface description file. When the ProjectReference attribute is Off, the project file for the library contains no GUID and the library specification is as follows

 <library
    id="ArrayFuncDll.dll"
    name="ArrayFuncDLL"
    migName="ArrayFuncDLL"
    location="c:\gmProj\lab\deploy\ArrayFuncDLL_std_csh\bin\ArrayFuncDLL.dll"
    type="Native"
 >
In addition, when a downstream project references this library, the reference is written as follows
 <Reference Include="ArrayFuncDLL">
    <HintPath>c:\gmProj\lab\deploy\ArrayFuncDLL_std_csh\bin\ArrayFuncDLL.dll</HintPath>
 </Reference>
When the ProjectReference property is On the project file for the library contains a GUID
<ProjectGuid>{EC869FCD-083F-4FE8-BB16-D4A1F44387C2}</ProjectGuid>
and the library specification in the IDF is as follows
 <library
    id="ArrayFuncDll.dll"
    name="ArrayFuncDLL"
    migName="ArrayFuncDLL"
    location="c:\gmProj\lab\deploy\ArrayFuncDLL_std_csh\ArrayFuncDll.csproj"
    uuid="{EC869FCD-083F-4FE8-BB16-D4A1F44387C2}"
    type="Native"
 >
Note that the location attribute is now the pathname of the project file and not the pathname of the binary assembly. Note also that the uuid attribute matches the ProjectGuid for the library.

When the downstream project authors its reference to this library, it notes that it has a uuid specified, and therefore it authors a ProjectReference as opposed to a simple Reference

  <ProjectReference Include="c:\gmProj\lab\deploy\ArrayFuncDLL_std_csh\ArrayFuncDll.csproj">
    <Project>{EC869FCD-083F-4FE8-BB16-D4A1F44387C2}</Project>
    <Name>ArrayFuncDLL</Name>
 </ProjectReference>
In the referencing code the setting of the ProjectReference attribute is ignored. Some libraries will have GUIDS and their reference will be authored using a ProjectReference; and some libraries will not have a GUID and their reference will be authored using a a simple reference. The ProjectReference attribute only directly controls how defining projects are authored.

When the ProjectReference property is On, a GUID is needed. The whole point behind the use of ProjectReferences is that this type of reference does a better job of keeping referenced binaries in sync with each other as code changes during ongoing development and debugging. The point of GUIDs is to ensure that a user of a library is using the correct version of that library. The system checks not only that the library names agree but also that the GUIDS agree.

Unfortunately, in real world migration projects the constant changing and syncing of GUIDS can make development and testing difficult. A simple change is made in a utility library, which causes a change in its GUID, which then requires that every downstream project be re authored as well. To give a bit more flexibility, setting the ProjectReference attribute On also requires that a "project" GUID be specified as well. That project GUID then can either be fixed or can be set to generate a new unique GUID on each translation of the library. The command script that defines the library has the following two statements added.

 <Select ProjectReference="on" />
 <Registry type="guid" source="Project" target="(%= Guid("new") %)" />
The first statement turns the ProjectReference attribute On. The registry statement then assigns a value to the "project" GUID. The Guid method attempts to find the named Guid in the registry. If it cannot find it, it creates a unique Guid. Since "new" does not exist, the above will assign a unique instance GUID to the Project GUID in the registry. If the same GUID is always wanted, the Registry command can simply specify it.
 <Registry type="GUID" source="Project" target="{11111111-2222-3333-4444-555555555555}" />

 Select Compiler Flag Attributes

The Compiler Flag attributes are on/off flags that control conventions used within the Compiler. When referenced within the gmSL they are boolean properties with On being True and Off being False.

 The AcceptByRef Compiler Flag Attribute

The AcceptByRef compiler flag attribute is used to control how explicit ByRef annotations are treated by the compiler when processing ASP code. Its values are as follows:

Value Description of use
On The compiler is forced to accept explicit ByRef parameters as ByRef regardless of what the uses of that parameter in the code seem to indicate. The property itself is used by the pass1 compiler, whose primary task is to build the symbol table, when it encounters the definition of a Sub or Function.
Off The ByRef specification is treated in the same manner as a missing specification.

The default value is Off

When a VB6 code is being processed, then this property has no effect. The problem and reason that the VB6 and ASP codes are treated differently relate to the type inference process. In the target, object-oriented languages, conversions and type weakening can occur when an argument is passed to a parameter by value. In particular, an argument of type object can be passed to almost any other type. When ByRef is used, however, an almost exact type-match is required. Because of this gmBasic resists making type inference changes for ByRef parameters. Since ASP parameters are always VARIANT and thus of type object in the target, very little type inference can be done. The user is forced to trade off type-inference versus getting the correct ByRef status. That is the role of this attribute.

 The CheckUUIDs Compiler Flag Attribute

The CheckUUIDs compiler flag attribute is used when gmBasic first loads an interface description file for a code reference. It purpose is to compare the UUID specified in the source reference request with the UUID specified on the library statement in the description file. Its values are as follows:

Value Description of use
Off Do not compare the reference UUID with the library UUID
On Do compare the UUIDs and issue warning messages if there are problems or differences.

The default value is Off

When the attribute is On and there is no UUID specified in the source reference then the following message is logged

   WARNING#102: This Project Reference has no UUID specified: (%= reference %)
If there is a source reference but it differs from the library one then the following is logged
   WARNING#003: The Project UUID (%= src_uuid %) and Library UUID (%= lib_uuid %) do not agree.
This attribute does not cause any error conditions, it merely issues warnings.

 The ShowReferences Compiler Flag Attribute

The ShowReferences compiler flag attribute describes how external references are being satisfied. It is used in multi project translations that have co referential projects. Given the build order within the command script a given reference can either be satisfied by a previous compilation in the same script or via an external library description. Its values are as follows:

Value Description of use
Off Do not log messages describing how external references are being satisfied.
On Do log messages describing how external references are being satisfied.

The default value is Off.

When On one of the following two messages is logged for each satisfied external reference.

   REFERENCE (%= reference %) satisfied within compilation.
       or
   REFERENCE (%= reference %) satisfied via library.

 The SortReferences Compiler Flag Attribute

The SortReferences compiler flag attribute controls the saving of a sorted symbol reference list for later analysis. Its value are as follows:

Value Description of use
Off Do not save a sorted symbol reference list.
On Do save a sorted symbol reference list.

The default value is On. It should not be turned Off. The sorted reference list is used extensively by the analyzer to trace argument values through subprogram calls.

 The LibrariesOnly Compiler Flag Attribute

The LibrariesOnly compiler flag attribute requests how external references should be satisfied. It is used in multi project translations that have co referential projects. Given the build order within the command script a given reference can either be satisfied by a previous compilation in the same script or via an external library description. Its values are as follows:

Value Description of use
Off In multi-project translations, attempt to satisfy references by first checking previously compiled projects within the current compilation script and then via referenced libraries specified by interface description files.
On Only use libraries specified via interface description files to satisfy component references.

Its default value is Off.

 The StructExtern Compiler Flag Attribute

The StructExtern compiler flag attribute specifies that primitive integer types in strucs should be declared using VB6 conventions. Its values are as follows:

Value Description of use
Off Requests Integer becomes int and Long becomes long
On Requests Integer becomes short and Long becomes int

The default value is Off.

 The SyntaxFatal Compiler Flag Attribute

The SyntaxFatal compiler flag attribute specifies how to handle syntax errors in the source code. Its values are as follows:

Value Description of use
Off Issue an error and continue processing.
On Issue an error and stop processing.

The default value is Off. Error causing source code statements are simply entered into the target translations as though they had been commented out in the source.

 The IgnoreWin32 Compiler Flag Attribute

The IgnoreWin32 compiler flag attribute specifies that DECLARES ignore the Win32 specification files as processed under the control of the CheckDeclares attribute. Its values are as follows:

Value Description of use
Off Process the WIN32 declaration definition files as controlled by the CheckDeclares property.
On Ignore the WIN32 declaration definition files and processing. Simply accept the declared interface as specified in the code.

The default value is Off.

 The AcceptRedefine Compiler Flag Attribute

The AcceptRedefine compiler flag attribute specifies how the compiler is to handle duplicate definitions of subprograms or variables in source codes. It has an effect when the pass1 compiler is processing a Sub,Function, or Dim statements and it encounters an identifier within the current scope level that has already been defined. The values are as follows:

Value Description of use
Off In this case redefines are not allowed and gmBasi generates a syntax error which says "Unable to store variable vector: 'identifier'" or "Unable to define subroutine 'identifier'". Note that pass1 syntax errors block further processing of the tool. When they occur no translation is attempted.
On In this case gmBasic the redefinition replaces the original one as opposed to being skipped.

The default value is Off.

 The ShowChanges Compiler Flag Attribute

The ShowChanges compiler flag attribute controls whether changes made to ASP VbScript code should be shown. gmBasic uses its VB6 compiler to process the VbScript code in ASP pages. There are instances where the compiler detects content that is not compatible with the VB6 compiler and changes it. The values are as follows:

Value Description of use
Off Do not show changes made to VbScript code
On Do show changes to VbScript code.

The default value is Off. The coding issues corrected are as follows:

  1. Replacing =< with <=
  2. Replacing isolated CR with a colon
  3. Remove Extra End if
  4. Insert : before Else Code
  5. Inserting colon after case Else
  6. Inserting colon after case value

 The OmitResxData Compiler Flag Attribute

The OmitResxData compiler flag attribute can be used to block the authoring of the resx files, but does not effect any other of the resource processing logic. Its values are as follows:

Value Description of use
Off Author resx files.
On Do not author resx files.

The default value is Off.

 The SupplyMissingResx Compiler Flag Attribute

The SupplyMissingResx compiler flag attribute specifies what to do with property value a when it is unable to open a referenced resx file.

Its values are as follows:

Value Description of use
Off If unable to open a reference resx file simply continue as though no resx file had been specified.
On Process the effected properties as though the resx file had been found but the property did not have a value given -- i.e. assign it a default value based on its type.

The default value is Off.

 The RuntimeConditional Compiler Flag Attribute

The RuntimeConditional compiler flag attribute specifies a work-around for complex compilation statements like
        #if cdCallStackDebug && ((CallStackDebug) ? -1 : 0) == 1
          if (!(myCallStack == null))
          {
             myCallStack.Enter(new object[]{CompID,"Initialize()"});
          }
       #endif
In .NET only simple exists/(does not exist) type conditional statements are allowed. This is a complex migration issue which requires further work but for the short term the goal is simply to build everything to be certain that the translations are all well-formed and reasonably well-typed. The work-around encloses the complex expression in quotes and then calls a MigrationSupport method TestCond. Thus the above becomes
          if (MigrationSupport.Lib.TestCond("cdCallStackDebug && ((CallStackDebug) ? -1 : 0) == 1"))
          {
             if (!(myCallStack == null))
             {
                myCallStack.Enter(new object[]{CompID,"Initialize()"});
             }
          }
The advantage of this approach is that all code within conditional blocks is built, not just that code in True blocks. The disadvantage is that this only works for conditional code, not for conditional declarations. Its values are as follows:

Value Description of use
Off Process conditionals in the manner specified by the ComputeConditionals attribute.
On Use migration support calls to hide the actual conditional expressions while still allowing the compiler to see all of the code within the condition.

The default value is Off.

 Select Analyser Flag Attributes

The Analyser Flag attributes are on/off flags that control conventions used within the Analyser. When referenced within the gmSL they are boolean properties with On being True and Off being False.

 The NullOrEmpty Analyser Flag Attribute

The NullOrEmpty Analyser flag attribute requests additional NullOrEmpty checks in the code. In particular, it scans the code looking for library components with the CanBeNull migration property set to On. When the source is testing them against an empty string, it tests them for a NULL or empty string. Its values are as follows:

Value Description of use
Off Do not do the extra code scan for CanBeNull migrations.
On Do the extra code scan for CanBeNull migrations.

The default value is Off.

 The TypeInference Analyser Flag Attribute

The TypeInference Analyser flag attribute requests that gmBasic author a TypeInference reference script which contains a list of all source code symbols associated with a code base that have had a type inferred for them by either the compiler, the analyser, or the user. The list itself consists of a set of Registry.Fixtype commands that specify the final type of any component whose type has been inferred during the translation process. Its values are as follows:

Value Description of use
Off Do not author a TypeInference script, but if there is a TypeInference script present in one of the search locations then it is loaded before the tool begins the first compilation. See the LoadEnvironment statement for details.
On After the analysis of the current compiled source code, write to the current local search location the current set of symbols with inferred types in the form of registry commands.

The default value is Off.

Using the TypeInferences attribute usually proceeds as follows. First the a few Registry.FixType statements are added to the translation script. These might look something as follows.

<Registry type="FixType" source="[<%=VirtualRoot%>\script\db_config.asp].SQLExecRS" target="ADODB.RecordSet" />
<Registry type="FixType" source="[<%=VirtualRoot%>\script\db_config.asp].GetTables" target="ADODB.RecordSet" />
<Registry type="FixType" source="[<%=VirtualRoot%>\script\db_config.asp].GetViews" target="ADODB.RecordSet" />
<Registry type="FixType" source="[<%=VirtualRoot%>\script\db_config.asp].GetColumns" target="ADODB.RecordSet" />
Using these statements gmBasic is now able to infer the types of many more components that need to be retained and then reapplied so that even more components can have their typing changed. This is the purpose of the TypeInferences attribute. After the first run the TypeInference script will contain registry commands that look exactly like the one above and will in addition contain registry commands for all new components whose types have been inferred. The TypeInference script always contains a cumulative list of all components whose types have changed.

When the script is being written gmBasic has stored all Registry.FixType entries that came either from the previous version of the script or from any such commands in the translation script itself. The first step is to scan this list for any symbols whose type has not been inferred during the current session. This can be true either because no additional inference was made or because the symbol is not involved in the present session. All these non-inferred symbols are written to the new script in exactly the same form as they were before. The second step is to scan all symbols in the current translation session and write any whose types have been inferred during the session. To emphasize, The TypeInference reference script is a migration-wide script. It contains the inferences made in all codes involved in the migration.

The Refactor.FixType commands do not make entries in the registry, but they do mark the symbols that they apply to as having been TypeInferred; therefore, these symbols will end up being in the script as well.

 The CodeCommentOut Analyser Flag Attribute

The CodeCommentOut analyser flag attribute specifies how warnings and error pragmas produced for specific upgrade issues are handled. Its values are as follows:

Value Description of use
Off When a reference to an unupgradable component occurs in the code add a conditional DEBUG warning to the code.
On When a reference to an unupgradable component occurs in the code simply add a comment naming the component.

The default value is Off.

As an example the following code is authored for references to some shape properties that cannot be upgraded when this attribute is Off

 #if !DEBUG
    #warning "UPGRADE ISSUE: Shape.FillColor was not upgraded."
 #endif
 // circRx.FillColor = System.Drawing.ColorTranslator.FromOle(Convert.ToInt32(LED_CENTER_OFF));
 #if !DEBUG
    #warning "UPGRADE ISSUE: Shape.BorderColor was not upgraded."
 #endif
 // circRx.BorderColor = System.Drawing.ColorTranslator.FromOle(Convert.ToInt32(LED_BORDER_OFF));
The same code is authored as follows when the attribute is On
 // Shape.FillColor
 // circRx.FillColor = System.Drawing.ColorTranslator.FromOle(Convert.ToInt32(LED_CENTER_OFF));
 // Shape.BorderColor
 // circRx.BorderColor = System.Drawing.ColorTranslator.FromOle(Convert.ToInt32(LED_BORDER_OFF));
Note that in both cases gmBasic still provides a reasonable translation for the unupgraded property, but then comments that translation out.

 Select Process Flag Attributes

The Process Flag attributes are on/off flags that control conventions used within the entire translation process or at least within more than one phase. When referenced within the gmSL they are boolean properties with On being True and Off being False.

 The UseOverload Process Flag Attribute

The UseOverload process flag attribute specifies if operator overloading should be used to migrate declarations and calls to methods with optional arguments. Its values are as follows:

Value Description of use
Off Indicates that overloads should not be used.
On Indicates that overloads should be used.

The default value is Off.

This attribute effects not just the authoring of subprograms with optional arguments, but also how they are called in the compiler. The statement that turns this attribute On must preceded the first Compile statement in its command script. It may be set in an Environment file.

 The UseZeroBased Process Flag Attribute

The UseZeroBased process flag attribute controls the adjustment of subscripts associated with 1-based dimensions. Its values are as follows:

Value Description of use
Off Do not adjust subscripts.
On Subscripts associated with 1-based dimensions are adjusted to be 0-based.

The default value is Off.

When this attribute is On: First if Option Base = 1, the pass1 compiler marks those variables that have explicit dimensions as having OptionBase1 subscripts; Second, the final pass of the analyser looks for references to the LBound and UBound functions applied to the variables marked and adjusts them by adding 1; Third, the author of the subscripts makes the appropriate adjustment to the dimension value in the declaration of the marked variables.

 The IssueWarnings Process Flag Attribute

The IssueWarnings process flag attribute controls the reporting of warnings throughout the translation process. Its values are as follows:

Value Description of use
Off Do not issue warning messages
On Issue warning messages

The default value is Off.

 The ImportsGlobal Process Flag Attribute

The ImportsGlobal process flag attribute specifies how references to external components should be handled for prototype migrations. Its values are as follows:

Value Description of use
On Requests that references will be accumulated so that the prototype assemblies contain all required elements.
Off Requests that references be reset for each migration unit.

The default value is Off.

When this attribute is On, rather than authoring any local stubs with the translated codes gmBasic instead either creates or updates a file in the current directory called ImportsGlobal_(%= langid %).xml which maintains a list of all referenced components in all imported references. See the description of the AuthorImports attribute which controls when a new ImportsGlobal file is created. Finally when gmBasic is asked to process this via the Author statement, it will author the stub code for it. The user can decide when the ImportsGlobal file should be deleted initially and when it should be authored and deployed.

To describe the use of this property in more detail assume there are four project codes, vb101.vbp, vb102.vbp, vb103.vbp, and vb104.vbp, that now build with their own local imports. Now it is time to but them together so that there is a single set of wrappers that contained the combined references of the four projects. This is what the process looks like.

First, since the imports global file accumulates reference information as the individual projects are processed, it is critical that the process gets a clean start. Thus, delete any existing copy of this file, before starting a translation sequence. Selects are then needed in the translation script for vb101.vbp.

   <Select AuthorImports="on" />
   <Select ImportsGlobal="on" />
The first select deletes any existing InportsGlobal file and the second authors an ImportsGlobal file containing the references imported by vb101.

Each of the translation scripts for vb102, vb103, and vb104 has only the ImportsGlobal="on" select. Thus the references for these projects will be accumulated. Note that the AuthorLibrary attribute should be set to deploy so the library description files are being written and read from the Local location.

Once all the individual projects have been processed, the statement

   <Author project="Importsfilename.xml" />
Authors a set of individual projects, one for each referenced external imports (not description files written by AuthorLibrary) which contain only those components needed by the group of projects. The first file that has to be built is of course the one produced by this step.

 The CheckMultiSet Process Flag Attribute

The CheckMultiSet process flag attribute controls the behavior of the type inference process when it encounters inferences to different user types being applied to the same component. Its values are as follows:

Value Description of use
Off Use the first user type inference encountered for the component.
On Use the last user type inference for the component.

The default value is Off.

 The RemoveByRef Process Flag Attribute

The RemoveByRef process flag attribute controls the treatment of ByRef parameters. In VB6, ByRef marshaling is the default and is very frequently used by accident, even with arguments that are often passed as literals or arithmetic expressions. C#, on the other hand is very strict and explicit about passing arguments by ref, and it is often necessary, in translations of VB6 to C#, to have to define a temporary variable only for the purpose of passing a literal or an expression ByRef. If the use of ByRef was not intentional, this added complexity is also unnecessary. Therefore, as an optimization, gmBasic inspects the body of the routine and removes ByRef marshalling when it is not needed. This provides for a cleaner translation because temporary argument variables are not created. Typically this optimization is not applied to arguments that were explicitly marked in the code as ByRef. Its values are as follows:

Value Description of use
Off Do not apply ByRef optimization to parameters that are explicitly declared ByRef.
On Apply the ByRef optimization to explicit ByRef parameters.

The default value is Off.

 The OmitOcxState Process Flag Attribute

The OmitOcxState process flag attribute controls the inclusion of OcxState information with resource files for ActiveX controls. Its values are as follows:

Value Description of use
On Exclude OcxState data from resource files.
Off Include OcxState data in resource files.

The default value is Off

 The UseLocalMemory Process Flag Attribute

The UseLocalMemory process flag attribute requests that only local memory be used for the storage areas created by Storage statements. Its values are as follows:

Value Description of use
Off Storage statements with Identifier attributes should use file based storage as specified.
On The Identifier attributes of Storage statements should be ignored.

The default value is Off.

File based storage is necessary if the results of a translation run are to debugged or audited. Almost all command scripts request file based storage via their Storage statement. gmBasic is using highly effective paging and symbol search algorithms to minimize file access times; however, memory based storage areas still have significantly faster access times. Turning the UseLocalMemory attribute On can greatly improve run times once a set of migrations is stable.

To use this attribute effectively a startup file should be used to turn the attribute On or Off. See the gmCL discussion for details on startup files.

 The OverLoadArguments Process Flag Attribute

The OverLoadArguments process flag attribute controls the check for OverloadArgument registry entries. OverLoadArgument is a terminal registry type that is stored in the globalsettings area. It is used to specify that individual subprogram arguments be overloaded to accept a list of different types. Its values are as follows:

Value Description of use
Off Do not check for OverloadArgument registry entries.
On Do check for OverloadArgument registry entries.

The default value is Off.

The OverloadArgument logic described under Registry statement is complex and difficult to implement. This attribute allows the user to begin and test the specifications needed in the GlobalSettings file without having to continually alter the entries in that file.

 The UsesInterfaces Process Flag Attribute

The UsesInterfaces process flag attribute controls the check for UsesInterfaces registry entries. UsesInterfaces is a terminal registry type that is stored in the globalsettings storage area. It is used to resolve references between independent projects that do not correspond to the build order. Its values are as follows:

Value Description of use
Off Do not check for UsesInterfaces registry entries.
On Do check for UsesInterfaces registry entries.

The default value is Off.

The UsesInterface logic described under Registry statement is complex and difficult to implement. This attribute allows the user to begin and test the specifications needed in the GlobalSettings file without having to continually alter the entries in that file.

 The SharedFile Process Flag Attribute

The SharedFile process flag attribute controls the check for SharedFile registry entries. SharedFile is a terminal registry type that is stored in the globalsettings storage area. It is used to identify those files that are used by more than one VB6 project and to identify which project should be the only one that processes it. Its values are as follows:

Value Description of use
Off Do not check for SharedFile registry entries.
On Do check for SharedFile registry entries.

The default value is Off.

The SharedFile logic described under Registry statement is complex and difficult to implement. This attribute allows the user to begin and test the specifications needed in the GlobalSettings file without having to continually alter the entries in that file.

 The AddDefaultProperties Process Flag Attribute

The AddDefaultProperties process flag attribute controls the decision to add default properties to singleton references to variant arguments. Some VB6 codes make extensive use of default properties. The problem with these occurs when calls are made to Variant arguments. If these are ultimately to be Objects then default properties are not wanted but if they are ultimately to be Values then default properties are wanted. Its values are as follows:

Value Description of use
Off Make the conservative choice and do not add default properties unless there is some certainty that they are appropriate.
On Make a more aggressive assumption about adding default properties. They are added whenever a Variant argument is being passed. Using this approach a few additional FixTypes are needed to avoid places where Objects like RecordSets that have an Object Property, such as Fields, as the default become inferred as the default property type and not the direct type.

The default value is Off


 The MigrationSupportUI Process Flag Attribute

The MigrationSupportUI process flag attribute controls the use of a MigrationSupportUI Form class that extends System.Windows.Forms.Form. VB6 forms can inherit from this class to give control over how and when the Load event is invoked. Its values are as follows:

Value Description of use
Off Do not use the new form class.
On Do use the new form class.

The default value is On.

The base class created when this attribute is On will only have a single public member named InvokeLoad() that should be called where Load is called in the VB6. Because of changes that need to happen around how and when the Load event is invoked, there is a need to inherit from a base class that extends System.Windows.Forms.Form. The intent here is to change the manner gmBasic deals with Form Loading in general.

 Storage Statement Summary

Storage is a terminal, command statement that occurs in command scripts. This statement specifies the status of the virtual binary information file to be used. It must be the first statement in the script and should always be included.

The attributes of the Storage statement are as follows:

Attribute Description
Action This required attribute specifies the storage action to be performed. It can have one of five options -- CREATE, OPEN, APPEND, CLOSE, and SAVE. These actions are described below.
Identifier This optional attribute is the full pathname of the file containing or to contain the information being stored. Optionally, the filename extension may be omitted. In which case the extension vbi is used. If this attribute is omitted, then a memory-based storage area is used. Memory-based storage is much quicker to use, but any information stored is lost when the run ends.
Startup This optional attribute is the full pathname of a file whose content should be used to initialize the current storage area when it is created. Optionally, the filename extension may be omitted. In this case, vbi is used. This attribute is only valid when a file-based storage area is being created. The content of the startup file itself is not changed.

The create action creates a new storage area. If no startup file is specified, then the storage area is initially empty. If the startup file is specified and the storage area is file-based, then it is initialized with the information in the startup file. In addition, if the startup file was closed with a save action, then the additional save runtime information is loaded as well.

The open action opens an existing file-based storage area for read- only access. No changes to the storage can be made.

The append action opens an existing file-based storage area for read-write access.

The close flushes any information being retained in memory for the storage area and the closes the storage file if it is file-based. Memory based storage areas are destroyed by the close.

The save action saves the internal tool runtime status information in the storage area and then performs a normal close operation. This ensures that when a later script uses this file for its startup, then the tool will be in the same state as when the previous save was performed.

Note that the UseLocalMemory select attribute can be used to override the Identifier attribute of this command. When UseLocalMemory is turned on, only memory-based storage areas are created.

 gmPL Utility Statements

The gmPL utility statements are like the command statements in that they are used within a gmBasic command script. Their role, however, is not to guide a translation but rather to perform a special operation to eventually aid a translation. The utility statements are as follows:

Statement Description of use
BuildOrder Reviews and orders a set of loaded project files so that they can be processed.
GlobalStubs Authors the stubs for a set of references that have been loaded previously via the Reference command.
Gmsl Introduces Great Migrations Scripting Language gmSL subprograms that can then be executed.
ImportList Rather than authoring any local stubs with the translated codes gmBasic can instead manage an ImportsGlobal file which maintains a list of all referenced components in all imported references. Once completed, this statement authors the stub code for them
IncludeOrder Reviews and orders a set of loaded ASP files so that they can be processed.
Load Loads the source compilation units so that they can be edited or ordered in preparation for processing.
Search Searches a virtual binary information file for symbols and produces reports as requested within the statement.
SharedFile Used after a set of VBP files have been loaded with the SourceCode attribute turned on. It scans the loaded form, class, and module files to see if any are loaded by more that one project.
gmNI-Utility Whenever gmBasic encounters a statement in a command script that it does not recognize, it searches each loaded runtime DLL for a handler of that statement. This makes it possible to add utility statements as needed by code migration projects.


 BuildOrder Statement Summary

BuildOrder is a terminal, utility statement that occurs in command scripts. It reviews and orders a set of loaded project files so that they can be processed in reference order. The projects to be ordered are first loaded using Load statements with their SourceCode attribute turned off; then, an Output statement is used to specify the file to receive the report; and finally, a BuildOrder statement creates the report.

The BuildOrder statement has no attributes or substatements and generates no script errors.

The report generated by the BuildOrder statement begins with two summary lines.

   The ordering over %d projects converged.
   There were %d order test iterations

Next there is a listing for each project in the established build order which shows the build order value for the project, the name of the project, and then a listing of each reference made the along with its build order or IDF status.

Next if there were unsatisfied references made these are listed. Finally a set of gmPL Compile statements are written, again in build order.

 GlobalStubs Statement Summary

GlobalStubs is a nonterminal, utility statement that occurs in command scripts. It authors the stubs for a set of references that have been loaded previously via the Reference statement. The statement is followed by a set of Load substatements which specify which compiled VBI files are to be used to determine which components in the references have been referenced.

The GlobalStubs statement itself has no attributes.

The substatements of the GlobalStubs statement are as follows:

Substatement Description
Load This substatement specifies the full pathname of a virtual binary information file via an id attribute. This file is loaded into a temporary storage area where it is searched for references to the components in the load references.

The script errors associated with the GlobalStubs statement are as follows:

Error Description
1064 Language command missing required id attribute.
1065 Unable to store Language id: %1d"
1066 The following record is not recognized: %1d

The typical script using the GlobalStubs statement would be as follows.

First, a storage statement is needed to hold the references to be loaded.

   <gmBasic>
      <Storage Action="Create" Identifier="..." />

Second, all of the standard locations need to be specified so that the reference files themselves can be located and loaded and the authored stubs can be sent to the desired deployment location.

      <Select DeployLocation="..." />
      <Select Library="..." />
      <select Target="..." />
      <Select Local="..." />
      <Select System="..." />

Third, a set of reference statements is used to specify the references for which stubs are to be authored. The actual declarations within these references are loaded in the storage area created above.

      <Reference id="..." />
      <Reference id="..." />
    ....
Fourth, an output statement is needed to specify the file to receive the authored stubs.
      <Output Status="New" Filename="GlobalStubs.bnd" />
Finally, the GlobalStubs statement itself is used to specify the previously compiled VBI files whose content makes references to components in the loaded references.
      <GlobalStubs >
         <Load id="...vbi" />
         <Load id="....vbi" />
             ....
         <Load id="....vbi" />
      </GlobalStubs>
      <Storage Action="Close" />
   </gmBasic>


 Gmsl Statement Summary

Gmsl is a nonterminal, utility statement that occurs in command scripts and within Refactor statements. The statement introduces Great Migrations Scripting Language gmSL subprograms that can then be executed. The conventions of gmSL itself are described elsewhere.

The attributes of the gmSL statement are as follows:

Attribute Description
NameSpace The required identifier of the namespace of the class. There is one reserved namespace gmSL that contains code called by gmBasic itself. At the present time the only class within this namespace is TextCode. The names of the methods within this class match the names of the text blocks currently defined in the language file. If at execution time for a text block, say Project_Preamble, if the tool has a gmSL.TextCode.Project_Preamble loaded then it will execute that code rather than authoring the text block. The other namespace convention relates to library refactoring files. Here the value of the event attribute of the refactor command is the required namespace.
Class The identifier of the class within the namespace that the code belongs to.
Source The name of the file that contains the source code to be compiled. If this attribute is omitted then the source is assumed to be contained within the script itself.

The gmSL statement has no substatements as such. When the Source attribute is omitted, the gmSL source itself is contained within the statement bounded by the Xml CDATA notation. This might look as follows.

  <gmSL namespace="gmSL" class="TextCode" ><![CDATA[
     Sub AddUserCompiles
      ...
     End Sub
 ]]></gmSL>
The script errors associated with the gmSL statement are as follows:

Error Description
1159 The gmSL attributes namespace and class are both required.
1160 Unable to open gmSL source file: %1d
1161 Unable to add project [%1d] to data storage area.
1162 Unable to add code [%1d] to data storage area.
1163 Encountered EOF while reading gmSL code from script.

In more detail, the gmSL statement directs gmBasic to compile a gmSL class and to store its code and symbol information so that it can be compiled by the standard compiler and can be executed by the standard execution engine. The standard compiler is a VB compiler; therefore, the source of the gmSL class itself may be written using VB syntax. There are plans underway to support JavaScript within the ASP processing capabilities of gmBasic. Once those are completed JavaScript syntax will also be available for gmSL.

 ImportList Statement Summary

ImportList is a nonterminal, utility statement that occurs only in ImportsGlobal scripts. It specifies the identifier of an external library whose components have been referenced by a group of code units. It contains a series of Referenced substatements which list the individual components within the external that were referenced. ImportsGlobal scripts are authored by gmBasic. Rather than authoring any local stubs with the translated codes gmBasic can instead manage an ImportsGlobal_(%= langid %).xml file which maintains a list of all referenced components in all imported references. See the Select attribute ImportsGlobal for a discussion of the process used to author these scripts.

The attributes of the ImportList statement are as follows:

Attribute Description
Id This attribute simply identifies the external library that has been referenced by the code units. It is a local filename like mso.dll or msword9.olb or mscomctl.ocx or msado20.tlb.

The substatements of the ImportList statement are as follows:

Substatement Description
Referenced This substatement specifies a particular component within the external that was referenced along with some information about that reference.


 Referenced ImportList Substatement Summary

Referenced is a terminal substatement of the ImportList statement. It specifies a particular component within the external identifier in the ImportList that was referenced along with some information about that reference.

The attributes of the Referenced substatement are as follows:

Attribute Description
Id This attribute is a qualified identifier, relative to the external library, of a component that was referenced and should be authored in the within the Global Stub.
Implemented This attribute is a flag whose On entry indicates that the component is part of an implemented interface.
Activex This attribute is a flag attributable to CoClasses whose On entry indicates the CoClass is a ActiveX control.
Hasforeach This attribute is a flag attributable to classes and coclasses whose On entry indicates that the component is used in ForEach and must, therefore, implement IEnumerable.
Constructor This attribute is a flag attributable to event handlers whose On entry indicates that they are being called directly within the code; therefore, their wrapper event arguments class requires a constructor.
Colobject This attribute is a flag attributable to the library whose On entry indicates that a reference component has a collection type; therefore, the library stub must import VBNET = Microsoft.VisualBasictype.
Eventargs This attribute is a flag attributable to event handlers whose On entry indicates that they have arguments.


 IncludeOrder Statement Summary

IncludeOrder is a terminal or nonterminal, utility statement that can occur only in command scripts. This statement computes the processing order of web site components based on their includes. The introduction of PageSlices largely deprecated the need for this statement; however, it is still useful for finding missing includes and missing references.

The terminal form of the IncludeOrder statement writes a report describing the results of the analysis. The nonterminal form authors a script contained in its substatements that can include the references found and the names of the pageslice files that have to be processed.

A command script using the IncludeOrder statement follows the following general form.

   <gmBasic>
      <Storage Action="Create" ... />
      <Select Local="..." />
      <Select System="..." />
      <Select Target="..." />
      <Load Page="filename(1)" />
           ...
      <Load Page="filemame(n)" />
      <Output Status="New" Filename="..." />
      <IncludeOrder ...
      <Storage Action="Close" />
   </gmBasic>
A major piece of the analysis performed by this statement involves finding all references to external components in the web site pages and verifying that those components are described via reference scripts stored in the search locations to be used when doing the translations. Therefore, those search locations must be specified here. The Load Page statements simple load the raw files into text buffers in the storage area so that they can be searched for external references and for includes.

The attributes of the IncludeOrder statement are as follows:

Attribute Description
Identifier This attribute is only used with the nonterminal form. It is a semicolon-delimited character string containing the parameter strings to be used when writing the substatement script. Each input record in that script is search for entries like %1d or %2d, etc. These are then replaced by the corresponding entry in this list.
Filename This attribute limits the analysis performed to the single page named by this attribute. This page must be one of the pages loaded. It can be helpful when initially setting up or for debugging particular issues that may be associated with the page.

The script errors associated with the IncludeOrder statement are as follows:

Error Description
1121 Unable to locate requested file: %1d
1122 Encountered EOF while reading search information.

The report generated by the terminal form IncludeOrder statement begins with three statements

   The ordering over %d pages converged.
   There were %d references missing:
       list of missing references
   There were 1 order test iterations
Then the pages loaded, or the single one requested along with its includes, are listed in their suggested build order along with a listing of the files that they include.

The intent of the report generated by the nonterminal form of the command is to author the actual command script to be used to do the PageSlice oriented site translations. In is described in the Fmstocks topic.

 Creating the Fmstocks Site Translation script

This discussions uses the Fmstocks sample ASP site to show how the IncludeOrder utility statement is used to aid in the creation of an initial PageSlice oriented translation command script. The Fmstocks code base consists of a set of VB6 projects and then a collection of ASP pages, some of which are only includes, that reference those projects. The assumption here is that the VB6 code has been translated and the libraries that it created have descriptions in the Local search location.

The first step is the create the initial IncludeOrder command script that will give an analysis report. This might look as follows

   <gmBasic>
      <Storage Action="Create" />
      <Select Local="C:\gmProj\FmStocks\IDF\FromCode" />
      <Select System="C:\gmProj\FmStocks\IDF\FromIDL" />
      <Select Target="C:\gmProj\FmStocks\IDF\FromIDL" />
      <Load Page=
          ...
      <Output Status="New" Filename="Order0.lst" />
      <IncludeOrder />
      <Storage Action="Close" />
  </gmBasic>
The problem, of course, are the Load Page statements. Web sites can contain thousands of pages. A simple way of generating this script is needed. In addition to the utility statements embedded within gmBasic there are also external utility statements available that are created via the gmNI and discussed under the gmNI Utilities topic. One of these is the LoadSite utility than is designed for just this type of situation. The command script needed to generate the needed IncludeOrder command script is simply
   <gmBasic>
   <Storage Action="Create" />
   <LoadRuntime dllName="Document.dll" />
   <Output Status="New" Filename="Order0.xml" />
   <LoadSite Directory="C:\gmSrc\fmstocks\WebSite" Extensions="asa,asp" >
   <gmBasic>
      <Storage Action="Create" />
      <Select Local="C:\gmProj\FmStocks\IDF\FromCode" />
      <Select System="C:\gmProj\FmStocks\IDF\FromIDL" />
      <Select Target="C:\gmProj\FmStocks\IDF\FromIDL" />
      <Load Page="%filename%" />
      <Output Status="New" Filename="Order0.lst" />
      <IncludeOrder />
     <Storage Action="Close" />
   </gmBasic>
   </LoadSite>
   <Storage Action="Close" />
  </gmBasic>
Running the command script produces an Order0.xml file that contains the needed set of Load Page statements. Running that script produces a report
   The ordering over 33 pages converged.
   There were 6 order test iterations
       ...
showing no missing references or missing includes, so the actual translation script can be authored by modifying the IncludeOrder statement in the script.
   <IncludeOrder Identifier="FmstockWeb;csh" >
   <gmBasic>
      <Storage Action="Create" Identifier="%1d"/>
      <Select DevEnv="VS2010" />
      <Select Dialect="%2d" />
      <Select Local="C:\gmProj\FmStocks\IDF\FromCode" />
      <Select System="C:\gmProj\FmStocks\IDF\FromIDL" />
      <Select Target="C:\gmProj\FmStocks\IDF\FromIDL" />
      <Select DeployLocation="C:\gmProj\FmStocks\Deploy\%1d_%2d" />
      <Select VirtualRoot="C:\gmSrc\FmStocks\WebSite" />
      %references%
      %compile%
      <Analyse />
      <Output Status="New" Filename="%1d.bnd" />
      <Author />
      <Storage Action="Close"/>
   </gmBasic>
   </IncludeOrder>
Running this script now produces the desired translation command script.
   <gmBasic>
      <Storage Action="Create" Identifier="FmstockWeb"/>
      <Select DevEnv="VS2010" />
      <Select Dialect="csh" />
         ...
      <Select DeployLocation="C:\gmProj\FmStocks\Deploy\FmstockWeb_csh" />
      <Select VirtualRoot="C:\gmSrc\FmStocks\WebSite" />
      <reference id="FMStocks_Bus.dll"/>
      <reference id="FMSStore_Bus.dll"/>
      <reference id="msado25.tlb"/>
      <reference id="FMStocks_Ext.dll"/>
      <reference id="FMStocks_DB.dll"/>
      <compile pageslice="C:\gmSrc\fmstocks\WebSite\401k.asp"/>
      <compile pageslice="C:\gmSrc\fmstocks\WebSite\AccountSummary.asp"/>
          ...
     <Analyse />
     <Output Status="New" Filename="FmstockWeb.bnd" />
     <Author />
     <Storage Action="Close"/>
 </gmBasic>
The name of the script and the desired dialect have been filled in. The meta variable %references% has been replaced by the set of needed Reference statements and the meta variable %compile% has been replaced by the needed set of Compile PageSlice statements.

 Load Statement Summary

Load is a nonterminal, utility statement that can occur only in command scripts. The statement loads source compilation units so that they can be edited, analysed, or ordered by other utility statements in preparation for processing.

The attributes of the Load statement are as follows:

Attribute Description
Project This attribute names a project file to be loaded in the same manner as the first step in the Compile statement. Loading the project file begins by first storing the name of the project file in the symbol table and making certain that it is unique. Second, the project file itself is loaded into an edit buffer. Third, the GlobalSettings file is checked to see if any edit fixes are to be applied to the project file. Fourth, the file is searched for the its Name and Exename32 entries whose values are then stored in the symbol table.
Sourcecode This flag attribute applies only to project loads. If on, the individual source files in the project are loaded. This involves searching the project file for Form, UserDocument, UserControl, Module, and Class entries whose values are the source code filenames to be loaded. Each file is then loaded into an edit buffer and its name is stored in the symbol table. For each file the GlobalSettings file is checked to see if any edit fixes are to be applied to it.
Page This attribute names a file in an ASP site to be loaded into a text buffer in raw form. This is not a PageSlice load as is performed by the compiler.

The substatements of the Load statement are as follows:

Substatement Description
Fix Using the Fix command statement as a substatement of the load restricts the range of application of the fixes to code files within the project or single page.

The script errors associated with the Load statement are as follows:

Error Description
1143 Encountered illegal LOAD directive %1d


 Search Statement Summary

Search is nonterminal, utility statement that occurs only in command scripts. It searches the currently open storage area for symbols and produces reports as requested within the statement.

The Search statement has no attributes.

The substatements within the Search statement are as follows:

Substatement Description
Symbols Produces a symbol listing
Details Produces a detailed symbol audit
Interface Displays a listing of the interface objects

The substatements all have the same attributes:

Attribute Description
Project This attribute contains the name of project. It restricts the reports to the symbols within that project.

To show what these reports contain Vb001 is a very simple code with one form. This search script for it

   <gmBasic>
      <Storage Action="Open" Identifier="C:\fkgtest\vb6test\csh\VB001.vbi" />
      <Output filename="vb001.txt" StripTrail="on" />
      <Search >
          <Symbols project="VB0001" />
          <Details project="VB0001" />
          <Interface project="VB0001" />
      </Search>
      <Storage Action="Close" />
  </gmBasic>
only audits the symbols in the project code itself. Much of the material in the audit reports is intended for use in the gmNI when working directly with the intermediate language. They are presented here only in a general sense.

 The Symbols Report for VB001

The report produced by the Symbols substatement is
Audit of Symbol tree in C:\fkgtest\vb6test\csh\VB001.vbi storage area:
Lev |  Address |   Parent | Symbol Type      | Full Symbol Identifier
--- |  ------- |   ------ | -----------      | ----------------------
  0 |     3692 |     2523 | FormFile         | VB0001.frm
  1 |    22730 |     3692 | Form             | VB0001.VB0001Form.VB0001Form
  2 |    22817 |    22730 | CommandButton    | VB0001.VB0001Form.VB0001Form.Command1
  1 |    22964 |     3692 | Subprogram       | VB0001.VB0001Form.Command1_Click
  2 |    23019 |    22964 | Variable         | VB0001.VB0001Form.Command1_Click.MyNumber
  0 |    22938 |     2523 | Vb_Name.3692     | VB0001.VB0001Form
The symbol table is hierarchical. The Lev column shows the nesting level relative to the root symbol of the symbol.

The Address column is the root address of the symbol. All symbols are assigned a unique root address in the symbol table. As will be seen later in this topic and as will be discussed fully within the gmNI topics these addresses remain constant over multiple translation runs. Since the same identifier is often used for many different components, finding specific references to components in the audit reports is often difficult. The address on the other hand are unique and are always appended to symbols in the detailed reports to make them easy to find.

The Parent column specifies the root address of the parent of the symbol in the hierarchical tree.

The Symbol Type column specifies the symbol object type. These are described more fully in the gmNI discussion.

The Full Symbol Identifier column is the fully qualifier identifier of the symbol. These identifiers are used to specify particular components in the Refactoring statements. They are relatively easy to construct but simply copying them out of an audit report is often easier.

 The Details Report for VB001

The Details report shows the detailed entries in the storage area for each symbol. The actual meaning of these entries is not in the scope of this discussion beyond knowing that they exist and generally the sort of information that they contain. The following shows the start of the information shown for the Command1_Click subprogram.
Detailed Description of Subprogram VB0001.VB0001Form.Command1_Click with root address 22964:
Property                       | Content
--------                       | -------
Migrate Status                 | SkipDecl
Migrate Flags                  | CodeAnalysed
Status Flags                   | Private
VB_Name                        | VB0001Form:22938
Binary Type                    | Void
Dimensions                     | 0
Triggering Control             | 22817:CommandButton:Command1
Triggering Event               | Click
Number of Arguments            | 0
Number Required                | 0
Address of Code                | 24517
Bytes of Code                  | 324

Actual C# Codeblock Associated with Command1_Click:
Offset |  Sl.Start |  Ql.Start | Quantity type | Opcode | Operation support information
------ |  -------- |  -------- | ------------- | ------ | -----------------------------
     0 |           |           |               | NEW    | 29 ChDir ".\"
     3 |           |           |               | LEV    | Nest0
     5 |       1.5 |       1.5 | String        | LSC    | 2:.\
    10 |       1.5 |           |               | ARG    | String
    12 |           |      1.12 | Void          | CMD    | ChDir
    14 |           |           |               | NEW    | 30 Open "VB0001.out" For Output As #2
    17 |           |           |               | LEV    | Nest0
    19 |      1.19 |      1.19 | String        | LSC    | 10:VB0001.out
    24 |      1.19 |           |               | ARG    | String
    26 |      1.19 |           |               | LEV    | Nest0
    28 |      2.28 |      1.28 | Integer       | LIC    | 2
    31 |      2.28 |           |               | ARG    | Integer
    33 |      2.28 |           |               | SPV    | PoundSign
    35 |      3.35 |      1.35 | OpenMode      | OMO    | Output
Codeblocks are the intermediate language forms of source code units. They are structured sequences of intermediate Opcodes -- operation identifiers -- that are manipulated by gmBasic and ultimately authored in the target language. This particular code is ready to be authored in C#.

 The Interface Report for VB001

The Interface report assumes that the symbol table contains components that are controls. The properties of these controls are displayed in the report.
Lev | Count | Status     | Role       | Object Type    | Object Identifier
--- | ----- | ------     | ----       | -----------    | -----------------
  1 |     0 | Ok         | Control    | Form           | VB0001Form
  2 |     0 | Ok         | Control    | CommandButton  | Command1
The symbol table is hierarchical. The Lev column shows the nesting level relative to the root symbol of the symbol.

The Count column shows "0" if the control is not a control array; else it shows the number of members in the control array.

The Status column shows the migration status of the component. By default it is Ok. It might also be Delete, Deprecated, NotImplemented, or MustCorrect.

The Role column shows the role that the component serves. By default it is Control. It might also be Event, Define, Resource, Migclass, Index, Property, Collection, or Utility.

The Object Type column specifies the symbol control type. These are described more fully in the gmNI discussion.

The Object Identifier is the identifier of the component as it was originally defined in the source.

 SharedFile Statement Summary

SharedFile is terminal, utility statement that can occur only in command scripts. It is used after a set of project files have been loaded with the SourceCode attribute turned on. It scans the loaded form, class, and module files to see if any are loaded by more that one project. It then reports the summary counts and gives a detailed listing of each shared file and the projects that use it.

The SharedFile statement has no attributes or substatements.

This utility is completely general and can be used for any multi-project application once the BuildOrder has been established. A sample script using it looks as follows.

    <gmBasic>
       <Storage Action="Create" Identifier="Shared" />
       <Select Target="..." Local=".." System=".." />
       <Load project="project(1).vbp" SourceCode="On" />
       <Load project="project(2).vbp" SourceCode="On" />
            .....
       <Load project="project(n).vbp" SourceCode="On" />
       <Output Status="New" Filename="SharedFile.out" />
       <SharedFile />
       <Storage Action="Close" />
    </gmBasic>
The projects must be loaded in build order. The SharedFile command then produces a report that starts off as follows (counts will clearly vary).
 There were 94 Shared Files in this group of projects: Modules = 55, Forms = 2 Classes = 37
 The Module file [module.bas] is shared by 258 projects
    (1) project(i).vbp
    (2) project(j).vbp
      ......
and it then concludes with a set of GlobalSettings registry commands that look as follows
 <Registry type="SharedFile" Source="module1.bas" Target="project(i).vbp" />
 <Registry type="SharedFile" Source="module2.bas" Target="project(k).vbp" />
 <Registry type="SharedFile" Source="module3.bas" Target="project(k).vbp" />
    .....
These SharedFiles are being used within other codes. They participate in the TypeInference algorithms and have their types inferred based on that other code. Once they are pulled out separately their types can no longer be changed by other codes. An IDF is needed to ensure this. The process goes as follows: First, the GlobalSetting Registry command SharedFile names the SharedFile as the Source and names that project to be used to establish the precise typing for the Shared File as the Target. Second, when the target project is processed it will produce the shared form of the file and it will also produce an IDF file for that code. Third, downstream projects, when their project files specify a SharedFile, would load the IDF not the actual file.

The convention used by the ShareFile utility statement above names the first project in encounters using the shared file as the target process. Henceforth these projects will be referred to as the "Defining" project for the shared file. Projects that load a SharedFile, but are not the Defining project will be termed a "Using" project of the shared file. Since the projects were loaded in BuildOrder this will ensure that there are no first-order circular references introduced -- i.e. the defining projects will also precede the using projects for every shared file. However, given that cross-references between shared and non-shared code will be present it is impossible to say how complex the circular reference problem will be for client codes that have them.

 gmniUtility Statements Summary

gmniUtility statements are made accessible to command scripts via a gmNI event. See the discussion under gmNI Command for information on implementing gmniUtility statements. This page describes those available in gmBasic. Using a gmniUtility statement is exactly like using any one of the other utility statements with one additional step, the Runtime Dll that implements the statement has to be loaded using LoadRuntime statement.

 AuditReferences gmniUtility Statement Summary

AuditReferences is a utility statement implemented by the ReferencesAudit runtime Dll. The compiler after it processes a subprogram, a property method, or an ASP page, scans the intermediate code produced and produces a sorted symbol reference list. For each symbol reference in the intermediate code the following six fields are saved:

Field Description of content
MAKES_REF The root offset of the subprogram, method, or page containing the reference to a symbol.
BEING_REFD The root offset of the symbol being referenced. This is the field upon which the reference list is sorted.
REC_NUMBER The text record number in the text buffer of the source statement that produced the reference. These text buffers are retained in the storage files produced by translation scripts. If the text buffer was edited via Fix statements then it is the edited version that is saved.
CODE_OFFSET The relative offset in the intermediate code of the actual symbol reference.
HOST_FILE The root offset of the information file containing the MAKES_REF code unit. This is the parent class, form, module, or page file.
TERMINAL If the reference to the symbol was terminal then True (1), else False (0). In a source code context an identifier like namespace.class.symbol has a terminal reference to symbol and nonterminal references to namespace and class. All three are retained.

This list is then used by the analyser to aid in its type inference decisions and in particular to trace argument values through subprogram calls. The AuditReferences report is a listing of the terminal references in this list.

The attributes of the AuditReferences statement are as follows:

Attribute Description
Storage This attribute specifies the full pathname of the storage file whose symbol references are to be audited.

The following command script produced this references report from the first VB6 project in the FMSTOCKS sample code.

   <gmBasic>
      <LoadRuntime dllName="ReferencesAudit.dll" />
      <Output filename="c:\gmBasic\AuditReferences.html" syntax="Html" />
      <AuditReferences Storage="fmstock1.vbi" />
   </gmBasic>
Note the use of Html syntax for the output file. This causes gmBasic to use Html annotations to write the table.

The columns in the report are as follows:

Column Description of content
Type If the MAKES_REF component is a control, then the type is GUI else the type is REF.
Member Name This is the identifier of the BEING_REFD symbol. Normally, this is simply the identifier associated with the symbol when it was initially stored in the symbol table. The special case has to do with properties that can have the Let, Get, and Set methods associated with then. When one of these methods is identified, it must be combined with the identifier of its parent property.
Member Class This is the class name of the BEING_REFD symbol. For symbols within library description files this is the name of the class or enumeration that contains the component. If the symbol is a variable, subprogram, constant, property, or enumeration, then this is the name associated with the code file that contains it. For higher level symbols within projects, this is the name of the project. For higher symbols in libraries, it is the library name.
Member Library This is the library name of the BEING_REFD symbol. For symbols within library description files this is the name of the library. For symbols within VB6 projects this is the name of the project. For any other symbols this is simply the identifier of the highest symbol in the tree above it but below the root.
Member Type This is the object type name of the BEING_REFD symbol. This is either an entry ObjectType enumeration in the language file, or a library reference type name, or a Basic built in class name, or the fully qualified identifier of the control if it is an external control class.
Loc Line If available, this is the line number in the source file of the reference.
Loc Text If available, this is the actual source statement that made the reference.
Loc Member This is the identifier of the MAKES_REF symbol. Normally, this is simply the identifier associated with the symbol when it was initially stored in the symbol table. The special case has to do with properties that can have the Let, Get, and Set methods associated with then. When one of these methods is identified, it must be combined with the identifier of its parent property.
Loc Path This is the pathname of the HOST_FILE component. For components within library description files the pathname is the hintpath of the library containing the component. For components within VB6 projects, this is the identifier of the file that contains the component. If no pathname can be found then it is simply blank.
Loc Name This is the class name of the MAKES_REF symbol. For symbols within library description files this is the name of the class or enumeration that contains the component. If the symbol is a variable, subprogram, constant, property, or enumeration, then this is the name associated with the code file that contains it. For higher level symbols within projects, this is the name of the project. For higher symbols in libraries, it is the library name.
Loc Type This is the file extension of the HOST_FILE component. For components within library description files it is the extension on the hintpath of the library containing the component. For components within VB6 projects, this is the extension the file that contains the component. If no extension can be found then it is simply blank.


 AuditDefinitions gmniUtility Statement Summary

AuditDefinitions is a utility statement implemented by the ReferencesAudit runtime Dll. It uses the same sorted symbol reference list as is used by the AuditReferences statement, but in a very different way. Its purpose is to detect how often user code symbols are used and in particular which user symbols are never used. The AuditDefinitions report is driven by a full traversal of the symbol table, though only source code symbols are included in the report. For each symbol, the symbol reference list is used to count its terminal references. This count along with the information about the symbol are then reported.

The attributes of the AuditDefinitions statement are as follows:

Attribute Description
Storage This attribute specifies the full pathname of the storage file whose symbol definitions are to be audited.

The following command script produced this definitions report from the first VB6 project in the FMSTOCKS sample code.

   <gmBasic>
      <LoadRuntime dllName="ReferencesAudit.dll" />
      <Output filename="c:\gmBasic\AuditDefinitions.html" syntax="Html" />
      <AuditDefinitions Storage="fmstock1.vbi" />
   </gmBasic>
Note the use of Html syntax for the output file. This causes gmBasic to use Html annotations to write the table.

The columns in the report are as follows:

Column Description of content
Type This is DEF:n where n is the nesting level of the symbol in the symbol table.
Member Name This is the identifier of the symbol. Normally, this is simply the identifier associated with the symbol when it was initially stored in the symbol table. The special case has to do with properties that can have the Let, Get, and Set methods associated with then. When one of these methods is identified, it must be combined with the identifier of its parent property.
Member Class This is the class name of the symbol. For symbols within library description files this is the name of the class or enumeration that contains the component. If the symbol is a variable, subprogram, constant, property, or enumeration, then this is the name associated with the code file that contains it. For higher level symbols within projects, this is the name of the project. For higher symbols in libraries, it is the library name.
Member Library This is the library name of the symbol. For symbols within library description files this is the name of the library. For symbols within VB6 projects this is the name of the project. For any other symbols this is simply the identifier of the highest symbol in the tree above it but below the root.
Member Type This is the object type name of the symbol. This is either an entry ObjectType enumeration in the language file, or a library reference type name, or a Basic built in class name, or the fully qualified identifier of the control if it is an external control class.
Num Refer This is the number of terminal references to the symbol. It may be zero.
Loc Text This is a declaration of the symbol. For variables, subprograms, property methods, and constants it is the Context flags associated with the symbol, followed by the symbol type, and the local identifier. For subprograms this is followed by a list of the argument types and calling status. For non quantity symbols it is simply the identifier.
Loc Path This is the pathname of the symbol. For components within library description files the pathname is the hintpath of the library containing the component. For components within VB6 projects, this is the identifier of the file that contains the component. If no pathname can be found then it is simply blank.
Loc Name This is the library name of the symbol. For symbols within library description files this is the name of the library. For symbols within VB6 projects this is the name of the project. For any other symbols this is simply the identifier of the highest symbol in the tree above it but below the root.
Loc Type This is the file extension of the symbol. For components within library description files it is the extension on the hintpath of the library containing the component. For components within VB6 projects, this is the extension the file that contains the component. If no extension can be found then it is simply blank.


 AuditExternals gmniUtility Statement Summary

AuditExternals is a utility statement implemented by the ReferencesAudit runtime Dll. It produces the same report format as the AuditReferences report, but only shows components in external libraries. Most importantly, the sorted references list is produced from the analysed code and not the simple compiled code and the range of application is greatly expanded. In addition to subprograms, property methods, and pages, the code in constants, enumeration entry values, and controls. is also searched. The report also includes the specific COM events that have event handlers in a given compilation unit. Finally, the references themselves are expanded to include things like sysRS!PropertyName = "Node Count" as a field reference; default item methods in collection classes when the code simply shows an COL.Item reference; and references to components in the MigrationSupport library that were hiding under operations codes.

The attributes of the AuditExternals statement are as follows:

Attribute Description
Storage This attribute specifies the full pathname of the storage file whose external symbol references are to be audited.

The following command script produced this externals report from the first VB6 project in the FMSTOCKS sample code.

   <gmBasic>
      <LoadRuntime dllName="ReferencesAudit.dll" />
      <Output filename="c:\gmBasic\AuditExternals.html" syntax="Html" />
      <AuditExternals Storage="fmstock1.vbi" />
   </gmBasic>
Note the use of Html syntax for the output file. This causes gmBasic to use Html annotations to write the table.

See the description of AuditReferences for a description of the content of the columns.

 gmPL Declaraction Statements

The gmPL declaration statements are organized into libraries and except for the Library statement itself are substatements of that command. The fundamental difference between the declaration statements and the other statement groups is that declaration statements are initially authored by gmBasic and then modified by the user as the translation process proceeds. The content of gmBasic authored declaration statements comes from two sources, Idl representations of external libraries and the translated code itself. The declaration statements are as follows:

Statement Description of use
Library Declares an external component like a dll, or an ocx, or an olb, or a tlb whose components are referenced by a source code but not defined within the source code.
Class Declares a class within a library.
Coclass Declares a class that is actually defined as the union of a set of classes.
Enumeration Declares an enumeration within a class or a library.
Method Declares a method within a class.
Argument Declares an argument within a method, event or accessor.
Property Declares a property within a class
GetSetLet Declares separate Get, Set, Let components within a property
Field Declares a property in a class whose origin was a class variable as opposed to a property.
Accessor Declares a property with both set and get access that has arguments.
Event Declares a event within a class.
Constant Declares a constant within a class or library.
Structure Declares a structure within a class or library
Typedef Declares a typedef within a library.

All components managed by gmBasic share three sets of flags -- context, status, and process. Each flag is a binary property -- on, off or true, false. Each flag has the same meaning regardless of the component that it is assigned to. Many of the attributes within the declaration statements manipulate these flags in various ways. The flags themselves are described in general as topics here. The phrase "is marked with a flag" is used to mean that the flag is turned On. In all cases, the default value of a flag for a given component is Off.

Declarations that define quantity components, components that have values, have a Type attribute that defines the binary type of those values. This attribute is the same for all declarations and is described here.

 Component Context flags

The component use context flags specify how the component is used, or is to be seen as used in its source context. The names of the context flags are in the ContextFlags enumeration in the language file. The flags themselves are as follows:

Flag Description
Private The component is declared as being private to the parent that contains it. This may because of an explicit declaration or it may be a flag added to the component for some reason.
Public The component is declared as being public. This normally means that it may be referenced anywhere in the code.
Static The component is declared as being static. This normally means that its parent keeps only one parent-wide value for the component as opposed to allocating a new value each time a parent object is created.
WithEvents The component was declared as being WithEvents. Which means that events can occur for the object for which event handlers might be present in the source code.
Argument The component is an argument of a subprogram or method or accessor or event.
ByVal The component is an argument which will be called by value.
ByRef The component is an argument which will be called by reference.
Foreign The component was referenced in a comprehensible way, but no definition of it could be found in either the user code or the libraries being referenced.
DeadCode The component has been marked as being dead code. This means that its declaration will be skipped. This flag has no effect on references to the component. See the Migration status flags for more information on dead component references.
UseGet The component requires the use of a "getter" to access its value.
ByOut The component is an argument whose value will be stored in the calling reference location when its subprogram exits.
Optional The component is an argument that may be optionally omitted when its subprogram is called.
NotDeclared The component is being used as a variable but was never declared.
FixedType The component has been assigned a type which should not be changed by the analyser.
Friend The component has the Friend status, which is derived but which often simply means that it was not explicitly declared to be public or private.
Overload The component needs to be explicitly given the Overload adornment when declared.
Dimensioned The component when declared was explicitly dimensioned via a size or set of size specifications. This size specification is stored as well.
Changed In processing the source code the compiler determined that the value of the component was being changed. This flag is later used by the algorithm that assigns arguments ByVal calling status.
New The component was declared as being new.
ParamArray The argument component is in fact a parameter array -- will contain a variable-length list of objects/values being passed to a subprogram.
InLibrary The component is allocated to an external library and its declaration may require extra adornments. This is used in particular with structures that are referenced via declare arguments.
IsDefault The component is the default component for its parent.
Collection The component is a collection class or a control vector.
Array The component is declared or is referenced as though it were an array even though it may not have been explicitly dimensioned.
2dArray The component is declared or is referenced as though it were a two-dimensional array even though it may not have been explicitly dimensioned.
Inferred The component has an inferred type.
Protected The component requires the protected adornment when it is declared.
InModule The component is declared within a module file.
Initial When the component is declared it should be initialized with the default initialization value for its type.
Resources The component has a set of resources associated with it that were originally stored in an frx file.
Passed The component is an argument whose calling status is unspecified, that has been passed to another subprogram. This flag is needed to trace the change status of that argument.


 Component status flags

The component status flags describe the status of the component relative to the overall migration. They can be assigned by gmBasic, but are also often declared via the declaration statements and are manipulated via the refactoring statements. The names of the status flags are in the MigStatusFlags enumeration in the language file. The flags themselves are as follows:

Flag Description
NotImplemented The component has no implementation in the target. References to it are commented out and adorned using "#if !DEBUG\n\t#error \sUPGRADE ISSUE: %1d was not upgraded.\s\n#endif\n"
Delete The component should be deleted from the target. References to it are literally removed from the target code.
CanBeNull The component itself, or its instances, are being for being empty. These instances can be Null as well. References to them in the intermediate code have to be checked if they are they are Null or Empty.
UserCode There may be runtime gmNI user code for processing this component. The identifier of this component, that triggers the event handler code, is specified for the component in its comment field.
External The component is external to the parent in the target implementation to which it was assigned in the source implementation. Therefore, when authoring the identifier of the component do not precede it with its source parent membership information.
NeedsInit In general this flag specifies whether the component needs to be initialized by the author in the target code. For control arrays, when the analyser detects an explicit reference to the control array in any subprogram code, it sets this flag for the control.
HasMigclass There is a user-defined or library-defined migClass that controls some aspect of the component.
LocalLibrary The library was formed as via a translation of a VB6 project within the migration set as opposed to being formed directly from an IDL file.
Remove References to the component should be removed as opposed to deleting and statements that reference the component. This is used primarily for subprograms and subprogram arguments.
ChangeParent This flag is deprecated and not currently used, though references to it may still exist in older reference files.
AddArgument This flag is used with subprograms. It indicates that an argument should be added to the argument list in the target translation.
CallPattern The surface form pattern associated with the component should be used when it is referenced, not when it is translated.
OverrideUser For components that are used to satisfy Implementation requirements, this flag forces the component to have the attributes as specified in the interface as opposed to as specified in the user code.
SkipDecl Set by the analyser to mark property setters and/or getters that can be skipped.
Static The component is static in the target implementation and thus any New creations must be removed.
IsDbNull The component is a class whose instances should be checked against DbNull as opposed to Null.
MustCorrect The component must be corrected in the target. References to it are commented out and adorned using "#if !DEBUG\n\t#error \sUPGRADE ISSUE: %1d was not upgraded.\s\n#endif\n"
Noncreatable The component class objects cannot be created. When declaring objects of this class simply NULL them as opposed to using new to create an instance.
SingletonRef The library component has been referenced as a singleton, without any class or parent designation. This may be an incorrect reference that has to be repaired.
StubOut Any code associated with the component should be ignored but a stub for the component should still be declared.
Override The subprogram component requires the Override specification when it is declared.
CastType The component does not require type casts when setting its values.
Referenced This flag is used by the author to mark those components that are actually referenced and that need to be included when authoring a wrapper.
SingletonUsed The library component has been used as a singleton, without any class or parent designation. This usage may be incorrect and in need of repair.
AppObject The component is an application wide singleton object which requires that special AppObject code be authored for it.
ArrayArray The component is two-dimensional but should be authored as a array of arrays -- e.g. [][] -- as opposed to [,].
Module The interface component is a module as opposed to a class, so its members may be referenced as singletons.
Implemented The class or interface component is implemented by another class in the current migration group.
ActiveX The coclass component is a control which can appear on a form; consequently there are special Ax naming conventions that must be used.
UsesCOM The component should be treated as though it were an ActiveX control.
BoxTypes This deprecated flag is used by the compiler when it encounters a potential late binding to this component. It checks if that late binding could be resolved if the reference were boxed to one of several types. If so do it, if not do the late binding. The CallByName refactoring statement provides an extensive facility for dealing with late bindings.


 Component Process Flags

The component process flags specify the details about the migration process associated with the component.They can be assigned by gmBasic, but are also often declared via the declaration statements and are manipulated via the refactoring statements. The names of the status flags are in the MigProcessFlags enumeration in the language file. The flags themselves are as follows:

Flag Description
CallBack When the main analyser logic encounters a reference to the VB6 function AddressOf then it must determine if the use of the AddressOf call is to establish a CallBack. If so then it marks both the method that is the callback and the argument receiving the AddressOf with the CallBack flag so that they can be dealt with properly by the author.
ZeroBased This is not set internally only via refactoring statements. It is used by the analyser to decrement subscripted references to components with this flag set.
WasActiveX When coclasses that were ActiveX controls are declared they are marked with this flag. It is used by the author to indicate the need to inherit from the Control class.
HasForEach This flag is attributable to classes and coclasses. It indicates that the component is used in ForEach and must, therefore, implement IEnumerable.
Constructor This attribute is a flag attributable to event handlers whose On entry indicates that they are being called directly within the code; therefore, their wrapper event arguments class requires a constructor.
ColObject This attribute is a flag attributable to the library whose On entry indicates that a referenced component within the class has a collection type; therefore, the library stub must import VBNET = Microsoft.VisualBasic.
HaveEventArgs This attribute is a flag attributable to event handlers whose On entry indicates that they have arguments.
NeedsLet This attribute is attributed to library methods to indicate that they are being used to set a property value and thus need a Let.
Implements When the compiler notes that a component is being used to implement a separate component it marks the implementing component with this flag.
Shadows 'Shadows' is yet another alternative to 'Overrides' and 'Overloads'. The 'Shadows' keyword indicates that a declared programming element shadows, or hides, an identically named element, or set of overloaded elements, in a base class. You can shadow any kind of declared element with any other kind. The purpose of shadowing is to protect the definition of the class members. It is used with Class, Const, Declare, Delegate, Dim, Enum, Event, Function, Interface, Property, Structure, and Sub Statements.
PropertyBag This attribute tells the property bag processor of to look for BeginProperty and NameValue pairs for this component.
RemoveResumeNext This attribute tells the analyser to turn off the "On Error Resume Next" to try-catch conversions for a particular subprogram. The algorithms used here are fairly robust, but can never be perfect. Specific codes may well encounter problems that are best dealt with by simply turning the algorithms off.
RemoveOnErrorGoTo This attribute tells the analyser to turn off the "On Error Goto" to try-catch conversions for a particular subprogram. The algorithms used here are fairly robust, but specific codes may well encounter problems that are best dealt with by simply turning the algorithms off.
Overloads The component requires the Overloads adornment when it is declared within VB.NET.
CodeAnalysed Indicates that the code associated with a code unit has already been analysed.
TypeInferred Indicates that the type of a component has been inferred.
InInterface Indicates that a component is in an interface
OptionBase1 First if Option Base = 1, the pass1 compiler marks those variables that have explicit dimensions as having OptionBase1 subscripts; Second, the final pass of the analyser looks for references to the LBound and UBound functions applied to the variables marked and adjusts them by adding 1; Third, the author of the subscripts makes the appropriate adjustment to the dimension value in the declaration of the marked variables.
FixedSource This attribute is applies to an ASP page once it has been processed by the Fix logic. Once this flag is set the page is skipped if it appears in a subsequent pageslice.
ObjectOnly Indicates that a quantity of type Variant or Object should not be type inferred.
BlockTemps This attribute is applied to subprograms. It blocks the formation of a TempArg when converting a Select into an If.
ArrayInfer Indicates that a quantity has had its array status inferred based on a reference to it in the code.
Exposed Only public symbols in classes are exposed in VB6 however in .NET module components can be exposed as well. The SharedFile logic marks these components accordingly.
SharedFile Not used
NotByRef Some value bearing components like members of structures, even in an indexed context, can not be passed by reference. This flag is used to indicate this.


 Declaration Type Attribute

This attribute specifies the binary type of the identifier. It consists of a type-specification followed by [] indicating that it is a 1-dimensional array, or [,] indicating that it is a 2-dimensional array, or [][] indicating that it is a 1-dimension array of 1-dimensional arrays There are a large number of built in types defined within gmBasic. First there are the basic types. The names of these types are considered to be reserved words. They are checked first when processing a type-specification before checking for a code defined type. These types are as follows:

VB6 .NET Equivalent C#, VB.NET
Byte byte, Byte
Short short, Short
Integer int, Integer
Long long, Long
Currency decimal, Decimal
Single float, Single
Double double, Double
String string, String
Boolean bool, Boolean
Date DateTime
Variant object, Object
Object object, Object
User object, Object
Control System.Windows.Forms.Control

Second, there are some IdlSpecial type names that appear in the IDL files and are passed through to the description files:

IdlSpecial .NET Equivalent C#, VB.NET
IUnknown object, Object
LongLong long, Long
Long int, Integer
stdole.IUnknown object, Object
Collection VBNET.Collection, Collection
Font System.Drawing.Font
stdole.Font System.Drawing.Font
OLE_COLOR System.Drawing.Color
stdole.IDispatch object, Object
stdole.OLE_COLOR System.Drawing.Color
None object, Object
BSTR string, String
VARIANT_BOOL bool, Boolean
OLE_HANDLE IntPtr
System.UInt32 int, Integer
System.Double Double
System.IntPtr IntPtr
System.Byte byte, Byte
System.Decimal decimal, Decimal

Third there the special processing types used by gmBasic to deal with various special circumstances:

Vb6Special .NET Equivalent C#, VB.NET
Icon System.Drawing.Icon
FrxPicture System.Drawing.Image
Any object, Object
TwipsX int, Integer
TwipsY int, Integer
UnsInteger unit, Integer
WinPanel System.Windows.Forms.GroupBox
VarArray Object[], Object()
StringPtr System.Text.StringBuilder, String
CallHwnd4 MigrationSupport.Vb7_Callback.Hwnd4
ControlCollection System.Windows.Forms.Control.ControlCollection
CheckedListBox System.Windows.Forms.ListBox
Exception System.Exception
SafeArray System.Array
SecurityManager UserSecurityManager
Dynamic dynamic
ValueType object, Object

Fourth are the VB6 classes:

Vb6Class .NET Equivalent C#, VB.NET
PictureBox System.Windows.Forms.PictureBox
Label System.Windows.Forms.Label
TextBox System.Windows.Forms.TextBox
Frame System.Windows.Forms.GroupBox
CommandButton System.Windows.Forms.Button
CheckBox System.Windows.Forms.CheckBox
OptionButton System.Windows.Forms.RadioButton
ComboBox System.Windows.Forms.ComboBox
ListBox System.Windows.Forms.ListBox
HScrollBar System.Windows.Forms.HScrollBar
VScrollBar System.Windows.Forms.VScrollBar
Timer System.Windows.Forms.Timer
Printer MigrationSupport.Printer
Form System.Windows.Forms.Form
DriveListBox Microsoft.VisualBasic.Compatibility.VB6.DriveListBox
DirListBox Microsoft.VisualBasic.Compatibility.VB6.DirListBox
FileListBox Microsoft.VisualBasic.Compatibility.VB6.FileListBox
Menu System.Windows.Forms.ToolStripMenuItem
MDIForm System.Windows.Forms.Form
Shape System.Windows.Forms.Label
Line System.Windows.Forms.Label
Image System.Windows.Forms.PictureBox
Data MigrationSupport.DataControl.DataControl
PropertyPage MigrationSupport.PropertyBag
TabControl System.Windows.Forms.TabControl
ErrObject VBNET.ErrObject, ErrObject

Fifth are the VB6 enumerations:

Vb6Enumeration .NET Equivalent C#, VB.NET
SimpleBorderStyle System.Windows.Forms.BorderStyle
KeyCodeConstants System.Windows.Forms.Keys
LogEventTypeConstants System.Diagnostics.EventLogEntryType
DrawStyle MigrationSupport.Lib.DrawStyle
DrawMode MigrationSupport.Lib.DrawMode
MousePointerConstants System.Windows.Forms.Cursor
WindowStyle VBNET.AppWinStyle, AppWinStyle
OpenMode VBNET.OpenMode, OpenMode
vbTristate VBNET.TriStatem TriState
ScaleType MigrationSupport.Lib.ScaleType
VbCompareMethod VBNET.CompareMethod, CompareMethod
VbFileAttribute VBNET.FileAttribute, FileAttribute
MsgBoxResult VBNET.MsgBoxResult, MsgBoxResult
VbMsgBoxStyle VBNET.MsgBoxStyle, MsgBoxStyle
VariableType VBNET.VariantType, VariantType
ButtonAppearanceStyle System.Windows.Forms.Appearance
ApplicationStartMode MigrationSupport.Lib.StartMode
MouseButtonConstants System.Windows.Forms.MouseButtons
ResourceType MigrationSupport.Lib.ResourceType
FirstDayOfWeek VBNET.FirstDayOfWeek, FirstDayOfWeek
FirstDayOfYear VBNET.FirstDayOfYear, FirstDayOfYear
DueDate VBNET.DueDate, DueDate
AlignConstants MigrationSupport.Lib.AlignConstants
CheckboxConstants System.Windows.Forms.CheckState
AlignmentConstants System.Drawing.ContentAlignment
BorderStyle System.Windows.Forms.FormBorderStyle
ComboBoxStyle System.Windows.Forms.ComboBoxStyle
ColorConstants System.Drawing.Color
LayoutArrangement MdiLayout
RLDirection System.Windows.Forms.RightToLeft
ShiftConstants MigrationSupport.Lib.ShiftConstants
BackStyle MigrationSupport.Lib.BackStyleConstants
QueryUnloadConstants MigrationSupport.Lib.QueryUnloadConstants
ClipboardConstants MigrationSupport.Lib.ClipboardConstants


 Declaration Status attribute

The context flags to be explicitly associated with components are often combined with each other in logical sets or are given names that resemble the equivalent names used in VB6 or IDL. These are defined in a metalanguage enumeration PropertyStatus and are specified via a Status attribute in various declaration statements. The entries are as follows:

PropertyStatus Equivalent context flags
SetByRef ByRef + UseGet
GetSet UseGet
GetSetLet UseGet
UseGet ByVal + UseGet
In ByVal
Out ByOut
InOut ByRef
Dimen ByVal + Dimensioned
ByVal ByVal
Static Static
ByRef ByRef
Indexer Collection
Protected Protected
ColItem Collection
Vector Array
ParamArray ParamArray
RefParamArray ByRef + ParamArray
AsNew ByRef + New


 Declaration MigStatus attribute

The various declaration statements all have On/Off flag attributes like External or CanBeNull that set the status of one of the context, status, or process flags described above. These are used to highlight the particular flags that are most often used with the type of component being declared. There is also a generic MigStatus attribute that can be used to set any flag or to specify a migration authoring fragment or to trigger a gmNI code event.

The attribute value is first checked to see if it consists of a sequence of MigStatusFlag entry names. These must be entered with no embedded blanks with each entry name except the first preceded by a plus or minus indicating that the flag should be turned on (+) or off (-). If there is no sign preceding the first entry, then it is assumed to be a plus.

If not a set of status flags, the attribute value is checked to see if it consists of a sequence of MigProcessFlag entry names. These must be entered with no embedded blanks with each entry name except the first preceded by a plus or minus indicating that the flag should be turned on (+) or off (-). If there is no sign preceding the first entry, then it is assumed to be a plus.

If neither a status nor a process flag, then that attribute value is assumed to be a user code string. The status flag UserCode is set and the string is stored as part of the component's description for later access by the analyser and the author. The analyser triggers a gmNI code event first during the initialization phase and second during the code review phase when it encounters a reference in the code to a component that has the UserCode status flag set. The triggered code event compares the first token of the user code string against the event identifiers of the currently active migration handlers. If a matching handler is found and if that handle has CodeEvent handler registered, then this service executes that handler.

The author looks for authoring fragments: Add1, Add2, and Type. It uses the first two when it is authoring the "AddRange" specification for a control. By default this is as follows for say a control called "ToolBar1"

    this.Toolbar1.Controls.AddRange(new System.Windows.Forms.Control[] {
             this.Toolbar1_Button1,
but the component that owns the "AddRange" method might not be "Controls" and the "AddRange" method argument might not be of the control class. The generic form of the above then becomes
    this.Toolbar1.%Add1%.AddRange(new %Add2%[] {
            this.Toolbar1_Button1,
and the specification status="Add1:Items,Add2:System.Windows.Forms.ToolStripItem" will make the above,
   this.Toolbar1.Items.AddRange(new System.Windows.Forms.ToolStripItem[] {
   this.Toolbar1_Button1,
It uses the Type when it is authoring the type declaration of an event argument without actually changing the type of the argument.

 Library Statement Summary

Library is a nonterminal, declaration statement that occurs primarily in reference scripts. It Introduces a library interface description file. The term "library" refers to an external component like a dll, or an ocx, or an olb, or a tlb whose components are referenced by a source code but not defined within the source code. Contemporary languages are extensible. Components can be added to the language processing environment that can be treated in exactly the same manner as core components in the language. These components have to be described to gmBasic. This is done via a Library specification. The term Interface refers to "those aspects of a language extension that can be referenced by statements in programs that use that extension". Historically, these referenced aspects of language extensions were simply libraries of subprograms that could be called by other programs. Though external components are far more complex now Library, remains the cover term.

Library description files are initially authored by gmBasic in one of two contexts. First, are the translations of IDL files describing COM components stored in the system and referenced by the source code being translated. These are called DescriptionFiles. Second, when gmBasic translates a VB6 project that can be referenced by other codes as an external reference, it also writes a description called a LocalDecriptionFile.

The attributes of the Library statement are as follows:

Attribute Description
Id This attribute simply identifies the external library being defined via its local filename like mso.dll or msword9.olb or mscomctl.ocx or msado20.tlb. For VB6 projects its source is the exename32 value from the project file.
Name This attribute is the identifier of the library from the IDL. It becomes the namespace for the library in the code. For VB6 projects, it is the Name value from the project file.
Uuid This attribute is the uuid specified in the IDL file. For VB6 projects the value of this attribute is controlled by the Select ProjectReference author flag. This attribute is often omitted.
Type This attribute specifies the type of external component that the library is. Its entries are from the LibraryType enumeration. Its values are Internal, Native, ActiveX, or LocalImport. For IDL libraries those with ocx extensions become ActiveX and the others are LocalImport. For VB6 projects it is always Native.
Space This deprecated attribute supplies an identifier to be used for the library in the target language.
Source This attribute is used for IDL authored libraries to document their source file name. It is not used by gmBasic beyond that.
Location This attribute specifies the target location of the actual external component being described by the declarations. It is typically authored using the %library% gmSL meta variable -- for example %library%\Interop.ADODB.dll. This assures that when the target project files are authored they will be reference as being in the actual library location for the migration set. Setting this attribute to DoNotDeclare blocks the inclusion of references to the external in the target project files.
Axlocation This attribute is used for IDL authored ActiveX libraries that are to be used as COM components. It declares the pathname of the AxInterop library.
Netversion This attribute is used for IDL authored libraries to document their version, if specified. It is not used by gmBasic beyond that.
MigName This attribute is used to specify the namespace to be used for the library, as opposed to the source namespace name, in the authored code.
Assemblyname This attribute is the assembly name to be used for the library in authored project files for Native libraries.
IdfStatus This attribute specifies how references to the library are to be treated. There five possible settings -- None, Build, Migrate, Interop and External. When the Buildfile Select is on then the default IdfStatus is Build. When BuildFile is off then the default IdfStatus is Migrate. The Interop setting is an intermediate one which says that any Mig files associated with the reference should be ignored. The External status blocks the authoring of stubs completely.

The substatements of the Library statement are as follows:

Substatement Description
Importlib A local substatement that declares an external reference made by the library.
Enumeration A declaration statement that defines an enumeration within the library.
Class A declaration statement that defines a class within the library.
Structure A declaration statement that defines a structure within the library
Union A declaration statement that defines a union within the library
Typedef A declaration statement that defines a typedef within the library.
Coclass A declaration statement that defines a class that is actually defined as the union of a set of classes
Migclass A refactoring statement that defines a class containing components needed to migrate the library to the target environment.

The script errors associated with the Library statement are as follows:

Error Description
1123 Library command missing required id attribute.
1124 Unable to store Library id: %1d
1125 Library command missing required name attribute.
1126 Unable to store Library id: %1d
1127 The library pattern type %1d is not defined.
1128 Importlib command missing required id attribute.
1129 The following library record is not recognized: %1d


 Importlib Library Substatement Summary

Importlib is a terminal substatement of the Library statement. Just as VB6 projects and ASP web sites reference external components, so do external components. This statement declares an external component used by the library being loaded. The ImportLib must appear at the beginning of the Library substatements since its components will be referenced by components in the library. The imported library itself is treated no differently than any other external reference when it is loaded, including the search though the selected search locations. If an import is already loaded, it is not loaded again.

The attributes of the Importlib substatement are as follows:

Attribute Description
Id This attribute specifies the library identifier of the library whose description is to be imported.


 Enumeration Statement Summary

Enumeration is a terminal or nonterminal declaration statement that occurs in reference scripts. It is also a metalanguage statement that is used to define not only enumerations in the source language, VB6, but also enumerations in the gmBasic languages themselves. An Enumeration is an identified set of (identifier, value) pairs. Each identifier in the Enumeration must be unique within the set. Each value in the Enumeration must be of the same type, but need not be unique. The value type can be any type including string and another enumeration. Each pair within the enumeration is referred to as an entry. Enumerations appear in both library and language descriptions; therefore, they also support all of the various migration attributes that can be associated with such components.

The terminal form of the Enumeration statement is used to deal with the forward reference problems in library declarations. It is often the case that a component in one class references another type defining component that has not yet been defined. Rather than trying to sort the definitions into a "reference" order, gmBasic, when it authors the declarations, adds a set of terminal Enumeration statements to the front of the library declaration with only the Id attribute specified. The later Enumeration statement with the same Id then specifies the remaining attributes and substatements.

The attributes of the Enumeration statement are as follows:

Attribute Description
Id The identifier of the enumeration used to contain its entries. It is stored in the scope of the containing component, unless that component is a class. See the private attribute below.
MigName If the enumeration is to appear in authored code then this attribute specifies the name to be used for it in that code.
MigStatus This attribute is a MigStatus attribute as discussed on the Declaration page. It contains generalized migration settings for the component.
Type This attribute specifies the type of the entry values. It may be integer, string, or another enumeration. If omitted, then the type is assumed to be integer.
Private This attribute is only relevant to enumerations within classes. If this attribute is On then the parent is the class. If this attribute is Off or omitted, then the parent is the library.
Structure This identifier attribute is used in metalanguage contexts in which enumerations can specify values to be associated with particular fields within a storage structure. This attribute contains the identifier of this structure.

The substatements within the Enumeration statement are as follows:

Substatement Description
Entry Defines one of the identifier, value pairs in the enumeration.

The script errors associated with the Enumeration statement are as follows:

Error Description
1111 Enumeration command missing required id attribute.
1112 Unable to store ENUMERATION vector: %1d
1113 Unable to find bridged ENUMERATION: %1d
1114 Unable to find structure for ENUMERATION: %1d
1115 Encountered following when expecting 'entry': %1d


 Entry Enumeration Substatement Summary

Entry is a terminal substatement of the Enumeration statement. It defines an identifier value pair within the enumeration. The attributes of the Entry substatement are as follows:

Attribute Description
Id This attribute is the identifier of the entry within the enumeration. It must be unique in that scope. It is not case sensitive.
value This attribute contains that value to be associated the entry. It must be of the type specified by the type attribute for the enumeration.
MigName If the enumeration entry is to appear in authored code then this attribute specifies the name to be used for this entry in that code.
MigStatus This attribute is a MigStatus attribute as discussed on the Declaration page. It contains generalized migration settings for the component.
Role This attribute contains an optional keyword describing the overall role of the class: Unknown, Property, Method, Define, Utility, Command, Constant, Function, Event, Control, Collection, Resource, Index, or Migclass. The default is None.
Description This attribute entry can be used to document the entry. It is not used by gmBasic.
Opcode This attribute is only used with metalanguage declarations. If the enumeration describes low level types within the user language, then this entry specifies the actual opcode.subcode byte pair to be issued by references to the entry.
MigPattern This string attribute associates a surface pattern string with code references to the entry. See the Patterns page for details on the content of pattern strings. It is equivalent to the All pattern.
CshPattern This string attribute associates a surface pattern string with code references to the entry. See the Patterns page for details on the content of pattern strings. It is equivalent to the Csh pattern.
VbnPattern This string attribute associates a surface pattern string with code references to the entry. See the Patterns page for details on the content of pattern strings. It is equivalent to the Vbn pattern.
Npram This integer attribute specifies the number of parameters associated with the surface pattern strings.
Subcode This attribute is only used with metalanguage declarations in which the parent enumeration has a structure specified. This attribute then specifies which field in the structure this entry relates to.

The script errors associated with the Entry substatement are as follows:

Error Description
1116 Enumeration entry missing required id attribute.
1117 Unable to store [%1d] as an enumeration entry.
1118 Bridge entry [%1d] cannot be found.
1119 The opcode cannot be found.
1120 Structure member entry [%1d] cannot be found.


 Class Statement Summary

Class is a terminal or nonterminal declaration statement that occurs primarily in reference scripts. It is also a metalanguage statement that is used to define not only classes in the source language VB6, but also classes in the gmBasic languages themselves.

The terminal form of the Class statement is used to deal with the forward reference problems in library declarations. It is often the case that a component in one class has the type of another type defining component that has not yet been defined. Rather than trying to sort the definitions into a "reference" order, gmBasic. when it authors the declarations, adds a set of terminal Class statements to the front of the library declaration with only the Id attribute specified. The later Class statements with the same Id then specify the remaining attributes and substatements.

The attributes of the Class statement are as follows:

Attribute Description
Id This attribute is the identifier of the class. It must be unique with the scope of the library containing the class. The identifier is not case-sensitive. This attribute must be specified on all declarations, be they terminal or nonterminal.
Parent This attribute is the identifier of the parent class of the class being declared. If omitted the class has no direct parent within the library.
Default This attribute is the identifier of some property or method within the class that is the "default". This is usually a property but may be an accessor or even a method. The default component allows the source code to reference class instances in singleton form -- i.e. not followed by ".member" -- in value contexts. These references are then assumed to be "instance.default" if a default was specified.
MigName This attribute supplies the name to be used for the class in the target translations.
MigStatus This attribute is a MigStatus attribute as discussed on the Declaration page. It contains generalized migration settings for the component.
Creatable This is an On/Off flag attribute. The Off setting sets the Noncreatable status flag On. It means that the component class objects cannot be created. When declaring objects of this class simply NULL them as opposed to using new to create an instance.
Role This attribute contains an optional keyword describing the overall role of the class: Unknown, Property, Method, Define, Utility, Command, Constant, Function, Event, Control, Collection, Resource, Index, or Migclass. The default is None.
Casttype This is an On/Off flag attribute. The Off setting sets the Casttype status flag On. This means that the class does not require type casts when setting its values.
AppObject This identifier attribute sets the AppObject status flag on and stores the identifier in the description table of the class. It means that the class has an application wide singleton object which requires that special AppObject code be authored for it.
Static This is a deprecated On/Off flag attribute. The On setting sets the External status flag On. It has been replaced by the External attribute.
Canbenull This is an On/Off flag attribute. The On setting sets the Canbenull status flag On. This means that when instances of this class are being for checked for empty, they must be checked for Null as well.
Module This is an On/Off flag attribute. The On setting sets the Module status flag On. This means that is was a module in VB6 as opposed to a class or Form, so its members may be referenced as singletons.
Opcode This identifier attribute is only used for metalanguage classes. It is the identifier of the operation code in the intermediate language that the members of this class emit.
Vectorsize This integer attribute is only used for metalanguage classes that are declaring gmSL object structures. It specifies the size of the structure associated with the object type.
Interfaces This attribute is a comma-delimited string of class identifiers that list the components that are implemented by the class being declared.
Implemented This is an On/Off flag attribute. The On setting sets the Implemented status flag On. It means the that class is implemented by another class in the current migration group.
External This is an On/Off flag attribute. The On setting sets the External status flag On. This means that the class is external to the library in the target implementation to which it was assigned in the source implementation. Therefore, when authoring the identifier of the class do not precede it with its source parent membership information.
NetName This identifier supplies a second name to be used for the class in the target translations. It allows the logic associated with generating migration support code to support multiple NameSpaces.

The declarations within the Class statement are as follows:

Substatement Description
Property Declares a property within a class
Field Declares a property in a class whose origin was a class variable as opposed to a property.
Method Declares a method within a class
Accessor Declares a property that with both set and get access that has arguments.
Event Declares a event within a class
Constant Declares a constant within a class
Enumeration Declares an enumeration within a class
Structure Declares a structure within a class
Attribute Declares an attribute within a metalanguage class

The script errors associated with the Class statement are as follows:

Error Description
1048 Class command missing required id attribute.
1049 Unable to store CLASS INTERFACE vector: %1d
1050 Unable to find parent CLASS: %1d
1051 The role keyword [%1d] is not recognized.
1052 The opcode cannot be found.
1053 Encountered following when expecting class component: %1d
1054 The default property [%1d] cannot be located.


 CoClass Statement Summary

Coclass is a terminal or nonterminal declaration statement that occurs only in reference scripts. It declares a class that is actually the union of a group of classes.

The terminal form of the Coclass statement is used to deal with the forward reference problems in library declarations. It is often the case that a component in one class has the type of another type defining component that has not yet been defined. Rather than trying to sort the definitions into a "reference" order, gmBasic when it authors the declarations places a set of terminal Coclass statements in the front of the library declaration with only the Id attribute specified. The later Coclass statements with the same Id then specify the remaining attributes and substatements.

The attributes of the Coclass statement are as follows:

Attribute Description
Id This attribute is the identifier of the coclass. It must be unique with the scope of the library containing the coclass. The identifier is not case-sensitive. This attribute must be specified on all declarations, be they terminal or nonterminal.
Role This attribute contains an optional keyword describing the overall role of the coclass: Unknown, Property, Method, Define, Utility, Command, Constant, Function, Event, Control, Collection, Resource, Index, or Migclass. The default is None. Coclasses often have a Control role.
MigName This attribute supplies the name to be used for the coclass in the target translations.
MigStatus This attribute is a MigStatus attribute as discussed on the Declaration page. It contains generalized migration settings for the component
Creatable This is an On/Off flag attribute. The Off setting sets the Noncreatable status flag On. It means that the coclass objects cannot be created. When declaring objects of this coclass simply NULL them as opposed to using new to create an instance.
CastType This is an On/Off flag attribute. The Off setting sets the Casttype status flag On. This means that the coclass does not require type casts when setting its values.
AppObject This identifier attribute sets the AppObject status flag on and stores the identifier in the description table of the coclass. It means that the coclass has an application wide singleton object which requires that special AppObject code be authored for it.
MigComment This deprecated string attribute associates a comment with the coclass. This comment does not trigger the gmNI event handlers.
Static This is an On/Off flag attribute. The On setting sets the External status flag On. This means that the coclass is external to the library in the target implementation to which it was assigned in the source implementation. Therefore, when authoring the identifier of the coclass do not precede it with its source parent membership information.
MigPattern This string attribute associates a surface pattern string with code references to the coclass. See the Patterns page for details on the content of pattern strings. It is equivalent to the All pattern.
CshPattern This string attribute associates a surface pattern string with code references to the coclass. See the Patterns page for details on the content of pattern strings. It is equivalent to the Csh pattern.
VbnPattern This string attribute associates a surface pattern string with code references to the coclass. See the Patterns page for details on the content of pattern strings. It is equivalent to the Vbn pattern.

The declarations within the Coclass statement are as follows:

Substatement Description
Subclass Identifies a class that is a member of the coclass.

The script errors associated with the Coclass statement are as follows:

Error Description
1058 Coclass command missing required id attribute.
1059 Unable to store coclass vector: %1d
1060 The role keyword [%1d] is not recognized.
1061 Encountered following when expecting 'subclass': %1d


 Subclass Coclass Subtatement Summary

Subclass is a terminal substatement of the Coclass statement. It identifies a class that is a member of the coclass.

The attributes of the Subclass substatement are as follows:

Attribute Description
Id This attribute is the identifier of a class within the same library that is a member of the coclass. Classes may be members of multiple coclasses.

The script errors associated with the Coclass statement are as follows:

Error Description
1062 Subclass command missing required id attribute.
1063 Unable to find subclass: %1d


 Structure Statement Summary

Structure is a terminal or nonterminal, declaration statement that occurs within Library statements and Class statements. Note that in description files authored from IDL-- i.e., external COM components -- there is also a Union statement (all members occupy the same location). In so far is gmBasic is concerned unions are treated in the same manner as structures. This statement has no refactoring or declaration flags associated with it.

The terminal form of the Structure statement is used to deal with the forward reference problems in library declarations. It is often the case that a member component of a type-defining component can have references to other types that have not yet been defined. Rather than trying to sort the type-defining declarations into a "reference" order, gmBasic, when it authors the declarations, places a set of terminal statements for all global type-defining components in the front of the library declaration with only the Id attribute specified. The later statements with the same Id then specify the remaining attributes and substatements.

The attributes of the Structure statement are as follows:

Attribute Description
Id This attribute is the identifier of the structure. It must be unique with the scope of the library or class containing the structure. The identifier is not case-sensitive. This attribute must be specified on all declarations, be they terminal or nonterminal.

The declarations within the Structure statement are as follows:

Substatement Description
Member Defines a member field within the structure

The attributes of the Member substatement are as follows:

Attribute Description
Id This attribute is the identifier of the member field. It must be unique with the scope of the containing the structure
Type This attribute is a Type attribute as discussed on the Declaration page. It specifies the type of the field.

The script errors associated with the Structure and Member statements are as follows:

Error Description
1043 Structure command missing required id attribute.
1044 Unable to store structure vector: %1d
1045 Encountered following when expecting 'member': %1d
1046 Member command missing required id attribute.
1047 Member command missing required type attribute.


 Method Statement Summary

Method is a nonterminal, declaration statement that occurs within Class statements and within the refactoring statement Migclass. It is also used within metalanguage class declarations and has some attributes that are only used in that context. A method is a coded procedure that may have arguments associated with it and that may return a value. The role of the declaration here is to specify those arguments, return value type. and any other needed migration/metalanguage information. What the method actually does, the code associated with its implementation, is not of interest here.

The attributes of the Method statement are as follows:

Attribute Description
Id This attribute is the identifier of the method. It must be unique within the scope of the class containing the method. The identifier is not case-sensitive.
Type This attribute is a Type attribute as discussed on the Declaration page. It specifies the return type of the method. Subprograms, methods that return no value, have a type Void.
Status This attribute is the Status attribute as discussed on the Declaration page. It specifies the various context flags to be associated with the method.
NetName This attribute is the identifier of the method to be used when declaring or referring to it in the target language.
MigName This attribute is identical to NetName. If both are used in the declaration the Migname takes precedence.
MigStatus This attribute is a MigStatus attribute as discussed on the Declaration page. It contains generalized migration settings for the component
MigComment This deprecated string attribute associates a comment with the method. This comment does not trigger the gmNI event handlers and can interfere with the MigStatus attribute.
MigPattern This string attribute associates a surface pattern string with code references to the method. See the Patterns page for details on the content of pattern strings. It is equivalent to the All pattern.
CshPattern This string attribute associates a surface pattern string with code references to the method. See the Patterns page for details on the content of pattern strings. It is equivalent to the Csh pattern.
VbnPattern This string attribute associates a surface pattern string with code references to the method. See the Patterns page for details on the content of pattern strings. It is equivalent to the Vbn pattern.
Npram This integer attribute specifies the number of parameters associated with the surface pattern strings.
Role This attribute contains an optional keyword describing the overall role of the operation being authored via the surface pattern strings: Unknown, Property, Method, Define, Utility, Command, Constant, Function, Event, Control, Collection, Resource, Index, or Migclass. The default is None.
Patstatus An optional keyword describing the overall status of the operation authored via the surface pattern strings: Ok, Delete, Deprecated, NotImplemented, MustCorrect, NotIdent, Postfix, or NeedsPren. The default is Ok.
OverrideUser This is an On/Off flag attribute. The On setting sets the OverrideUser status flag On. For components that are used to satisfy Implementation requirements, this flag forces the component to have the attributes as specified in the interface as opposed to as specified in the user code.
Overload This is an On/Off flag attribute. The On setting sets the Overload context flag On. The method needs to be explicitly given the Overload adornment when declared.
Overridecall This is an On/Off flag attribute. The On setting sets the CastType status flag On. This means that the method does not require type casts when setting its values.
Canbenull This is a On/Off flag attribute. The On setting sets the CanbeNull status flag On. This means that checks of the return value for being empty can be Null as well. References to them in the intermediate code have to be checked if they are they are Null or Empty.
Opcode This attribute is only used with metalanguage declarations. It specifies the actual opcode.subcode byte pair to be issued by references to the method as opposed to the normal call operations.
Syntax This attribute indicates that the method uses special syntax for specifying its arguments. The syntax types are Line, Pset, Scale, Print, and Event.

The declarations within the Method statement are as follows:

Substatement Description
Argument Defines one of the method arguments.

The script errors associated with the Method statement are as follows:

Error Description
1130 Method command missing required id attribute.
1131 Unable to store METHOD vector: %1d
1132 The syntax cannot be found.
1133 The subprogram type is undefined.
1134 Encountered following when expecting 'argument': %1d


 Argument Statement Summary

Argument is a terminal, declaration statement that occurs within method, accessor, and event statements. It declares a calling argument of its parent.

The attributes of the Argument statement are as follows:

Attribute Description
Id This attribute specifies the identifier of the argument. It must be unique in so far as the other arguments in the method are concerned. It is not case sensitive.
Type This attribute is a Type attribute as discussed on the Declaration page. It specifies the type of the argument.
Status This attribute is the Status attribute as discussed on the Declaration page. It specifies the various context flags to be associated with the argument.
Optional This string attribute specifies that the argument is optional in calls to the method and what the default value should be used to replace the missing argument. Its possible settings are below.
NetName This attribute is the identifier of the argument to be used when declaring or referring to it in the target language.
MigName This attribute is identical to NetName. If both are used in the declaration the Migname takes precedence.
MigStatus This attribute is a MigStatus attribute as discussed on the Declaration page. It contains generalized migration settings for the argument.
Changed This is an On/Off flag attribute. The On setting sets the Changed context flag On. This means that in processing the source code the compiler determined that the value of the argument was being changed. This flag is later used in by the algorithm that assigns arguments ByVal calling status.
MigPattern This string attribute associates a surface pattern string with code references to the argument. See the Patterns page for details on the content of pattern strings. It is equivalent to the All pattern.
CshPattern This string attribute associates a surface pattern string with code references to the argument. See the Patterns page for details on the content of pattern strings. It is equivalent to the Csh pattern.
VbnPattern This string attribute associates a surface pattern string with code references to the argument. See the Patterns page for details on the content of pattern strings. It is equivalent to the Vbn pattern.

The Optional attribute can have the following entries:

Entry Replacement value supplied
DEF.MissingZero 0
DEF.MinusOne -1
DEF.MoveTop 0
DEF.MoveWidth 0
DEF.MoveHeight 0
DEF.TypeMissing Type.Missing
DEF.Overload no value supplied
DEF.EmptyString String.Empty
DEF.NullObject Nothing or null
RefZeroObj ref objZero
DoubleQuote ""
DateTime New DateTime(0) or DateTime.MinValue
Default The zero initialization value of the type of the argument
string string

The script errors associated with the Argument statement are as follows:

Error Description
1135 Argument command missing required id attribute.
1136 Unable to store argument vector: %1d
1137 Argument command missing required type attribute.
1138 Argument status [%1d] is not defined.


 Property Statement Summary

Property is a nonterminal declaration statement that occurs within Class statements and within the refactoring statement Migclass. It is also used within metalanguage class declarations and has some attributes that are only used in that context. A property has a value, but that value is maintained via three possible methods Get, Set, and Let. References to properties in the code typically can look just like references to fields, but not always. In migrating properties it is often necessary to treat the methods that actually implement the property differently.

The attributes of the Property statement are as follows:

Attribute Description
Id This attribute is the identifier of the property. It must be unique within the scope of the class containing it. The identifier is not case-sensitive.
Type This attribute is a Type attribute as discussed on the Declaration page. It specifies the type of the property.
Status This attribute is the Status attribute as discussed on the Declaration page. It specifies the various context flags to be associated with the property.
NetName This attribute is the identifier of the property to be used when declaring or referring to it in the target language.
MigName This attribute is identical to NetName. If both are used in the declaration the Migname takes precedence.
MigStatus This attribute is a MigStatus attribute as discussed on the Declaration page. It contains generalized migration settings for the property.
MigComment This deprecated string attribute associates a comment with the property. This comment does not trigger the gmNI event handlers and can interfere with the MigStatus attribute.
Default This string attribute associates a default string with the property for use in designer code. This string does not trigger the gmNI event handlers and can interfere with the MigStatus attribute.
Value This identifier attribute is used in refactoring Migclass properties to specify the property in the class being migrated that supplies the designer code value.
MigPattern This string attribute associates a surface pattern string with code references to the property. See the Patterns page for details on the content of pattern strings. It is equivalent to the All pattern.
CshPattern This string attribute associates a surface pattern string with code references to the property. See the Patterns page for details on the content of pattern strings. It is equivalent to the Csh pattern.
VbnPattern This string attribute associates a surface pattern string with code references to the property. See the Patterns page for details on the content of pattern strings. It is equivalent to the Vbn pattern.
Npram This integer attribute specifies the number of parameters associated with the surface pattern strings.
Role This attribute contains an optional keyword describing the overall role of the operation being authored via the surface pattern strings: Unknown, Property, Method, Define, Utility, Command, Constant, Function, Event, Control, Collection, Resource, Index, or Migclass. The default is None.
Patstatus An optional keyword describing the overall status of the operation authored via the surface pattern strings: Ok, Delete, Deprecated, NotImplemented, MustCorrect, NotIdent, Postfix, or NeedsPren. The default is Ok.
Canbenull This is an On/Off flag attribute. The On setting sets the CanbeNull status flag On. This means that checks of the property value for being empty can be Null as well. References to them in the intermediate code have to be checked if they are Null or Empty.
External This is an On/Off flag attribute. The On setting sets the External status flag On. This means that the property is external to the class in the target implementation to which it was assigned in the source implementation. Therefore, when authoring the identifier of the property do not precede it with its source parent membership information. The use of this attribute assumes that the MigName attribute was used as well to supply a qualified target language name.
Opcode This attribute is only used with metalanguage declarations. This entry specifies the actual opcode.subcode byte pair to be issued by references to the property as opposed to the normal reference operations.

The substatements within the Property statement are only used if one of the two Status entries GetSet or GetSetLet were specified. They are as follows:

Substatement Description
Get This substatement defines special processing to be performed for the Get operation associated with the property.
Set This substatement defines special processing to be performed for the Set operation associated with the property.
Let This substatement defines special processing to be performed for the Let operation associated with the property.

The script errors associated with the Property statement are as follows:

Error Description
1141 Property command missing required id attribute.
1142 Unable to store property vector: %1d


 GetSet Statement Summary

Get, Set, and Let are terminal, substatements of the Property statement. They can also occur within Migrate refactoring statements that are changing the GetSetLet status of a property. A property has a value but that value is maintained via three possible methods: Get which retrieves the value of the property; Set which assigns an object instance to the property; and Let which assigns a value to the property. These substatements are used when these operations in the target language must be handled differently.

The attributes of the Get, Set, and Let substatements all pertain to the authoring of the property in the context of the operation being performed. They are as follows:

Attribute Description
MigPattern This string attribute associates a surface pattern string with code references to the property of the indicated type. See the Patterns page for details on the content of pattern strings. It is equivalent to the All pattern.
CshPattern This string attribute associates a surface pattern string with code references to the property of the indicated type. See the Patterns page for details on the content of pattern strings. It is equivalent to the Csh pattern.
VbnPattern This string attribute associated a surface pattern string with code references to the property of the indicated type. See the Patterns page for details on the content of pattern strings. It is equivalent to the Vbn pattern.
Npram This integer attribute specifies the number of parameters associated with the surface pattern strings.
Role This attribute contains an optional keyword describing the overall role of the operation being authored via the surface pattern strings: Unknown, Property, Method, Define, Utility, Command, Constant, Function, Event, Control, Collection, Resource, Index, or Migclass. The default is None.
Patstatus An optional keyword describing the overall status of the operation authored via the surface pattern strings: Ok, Delete, Deprecated, NotImplemented, MustCorrect, NotIdent, Postfix, or NeedsPren. The default is Ok.

The script errors associated with the Get, Set, or Let statements are as follows:

Error Description
1038 Encountered following when expecting 'get', 'set', or 'let': %1d
1039 Unable to store argument vector: %1d

As an example of these statements this is a property declaration within the Mscomctllib.IListView class, that migrates IListView.SelectedItem.Get to FocusedItem

  <property id="SelectedItem" type="Tab" status="GetSetLet">
     <Get npram="1" migPattern="%1d.FocusedItem"/>
     <Set npram="2" migPattern="%1d.SelectedItem = %2d\c"/>
     <Let npram="2" migPattern="%2d.let_SelectedItem(%1d)\c"/>
  </property>
Note that letters of the form obj.let_Property(value) are another Interop holdover that do not make sense in a migrated native code. They are ignored here for Global builds.

As an example of these statements within a Migrate statement, consider this migration of MSComCtl2.IMonthView.Value

  <Migrate id="IMonthView.Value" status="GetSet" >
      <Get nPram="1" migPattern="%1d.SelectionStart" />
      <Let nPram="2" migPattern="%2d.SetDate(%1d)\c" />
 </Migrate>


 Field Statement Summary

Field is a terminal declaration statement that occurs within Class statements. They appear only in LocalDecriptionFiles -- descriptions of external references whose source was a VB6 project within the code set being processed. The source of fields are global class variables. In the source code they are referenced in exactly the same way as InOut properties. There are two important differences, however, between variables and properties. .NET does not allow settable properties to be passed ByRef and does not allow fields to belong to interfaces. The Field statement declares these global variables and stubs them as global variables so that they can be passed ByRef. In interfaces, however, and in every other context they are treated as InOut properties.

The attributes of the Field statement are as follows:

Attribute Description
Id This attribute is the identifier of the field. It must be unique within the scope of the class containing it. The identifier is not case-sensitive.
Type This attribute is a Type attribute as discussed on the Declaration page. It specifies the type of the field.
Status This attribute is the Status attribute as discussed on the Declaration page. It specifies the various context flags to be associated with the field.
NetName This attribute is the identifier of the field to be used when declaring or referring to it in the target language.
MigName This attribute is identical to NetName. If both are used in the declaration the Migname takes precedence.
MigStatus This attribute is a MigStatus attribute as discussed on the Declaration page. It contains generalized migration settings for the field.
MigComment This deprecated string attribute associates a comment with the field. This comment does not trigger the gmNI event handlers and can interfere with the MigStatus attribute.
MigPattern This string attribute associates a surface pattern string with code references to the field. See the Patterns page for details on the content of pattern strings. It is equivalent to the All pattern.
CshPattern This string attribute associates a surface pattern string with code references to the field. See the Patterns page for details on the content of pattern strings. It is equivalent to the Csh pattern.
VbnPattern This string attribute associates a surface pattern string with code references to the field. See the Patterns page for details on the content of pattern strings. It is equivalent to the Vbn pattern.
Npram This integer attribute specifies the number of parameters associated with the surface pattern strings.
Role This attribute contains an optional keyword describing the overall role of the operation being authored via the surface pattern strings: Unknown, Property, Method, Define, Utility, Command, Constant, Function, Event, Control, Collection, Resource, Index, or Migclass. The default is None.
Patstatus An optional keyword describing the overall status of the operation authored via the surface pattern strings: Ok, Delete, Deprecated, NotImplemented, MustCorrect, NotIdent, Postfix, or NeedsPren. The default is Ok.
Canbenull This is an On/Off flag attribute. The On setting sets the CanbeNull status flag On. This means that checks of the field value for being empty can be Null as well. References to them in the intermediate code have to be checked if they are Null or Empty.
External This is an On/Off flag attribute. The On setting sets the External status flag On. This means that the field is external to the class in the target implementation to which it was assigned in the source implementation. Therefore, when authoring the identifier of the field do not precede it with its source parent membership information. The use of this attribute assumes that the MigName attribute was used as well to supply a qualified target language name.

The script errors associated with the Field statement are as follows:

Error Description
1141 Property command missing required id attribute.
1142 Unable to store property vector: %1d


 Accessor Statement Summary

Accessor is a nonterminal, declaration statement that occurs within Class statements within description files authored from IDF-- i.e., external COM components. It declares a property with both set and get access that has arguments.

The attributes of the Accessor statement are as follows:

Attribute Description
Id This attribute is the identifier of the accessor. It must be unique within the scope of the class containing the accessor. The identifier is not case-sensitive.
Type This attribute is a Type attribute as discussed on the Declaration page. It specifies the value type of the accessor.
Status This attribute is the Status attribute as discussed on the Declaration page. It specifies the various context flags to be associated with the accessor.
NetName This attribute is the identifier of the accessor to be used when declaring or referring to it in the target language.
MigName This attribute is identical to NetName. If both are used in the declaration the Migname takes precedence.
MigStatus This attribute is a MigStatus attribute as discussed on the Declaration page. It contains generalized migration settings for the accessor.
MigComment This deprecated string attribute associates a comment with the accessor. This comment does not trigger the gmNI event handlers and can interfere with the MigStatus attribute.
MigPattern This string attribute associates a surface pattern string with code references to the accessor. See the Patterns page for details on the content of pattern strings. It is equivalent to the All pattern.
CshPattern This string attribute associates a surface pattern string with code references to the accessor. See the Patterns page for details on the content of pattern strings. It is equivalent to the Csh pattern.
VbnPattern This string attribute associates a surface pattern string with code references to the accessor. See the Patterns page for details on the content of pattern strings. It is equivalent to the Vbn pattern.
Npram This integer attribute specifies the number of parameters associated with the surface pattern strings.
Role This attribute contains an optional keyword describing the overall role of the operation being authored via the surface pattern strings: Unknown, Property, Method, Define, Utility, Command, Constant, Function, Event, Control, Collection, Resource, Index, or Migclass. The default is None.
Patstatus An optional keyword describing the overall status of the operation authored via the surface pattern strings: Ok, Delete, Deprecated, NotImplemented, MustCorrect, NotIdent, Postfix, or NeedsPren. The default is Ok.
Canbenull This is an On/Off flag attribute. The On setting sets the CanbeNull status flag On. This means that checks of the value for being empty can be Null as well. References to them in the intermediate code have to be checked if they are Null or Empty.

The declarations within the Accessor statement are as follows:

Substatement Description
Argument Defines one of the accessor arguments.

The script errors associated with the Accessor statement are as follows:

Error Description
1130 Method command missing required id attribute.
1131 Unable to store METHOD vector: %1d
1132 The syntax cannot be found.
1133 The subprogram type is undefined.
1134 Encountered following when expecting 'argument': %1d


 Event Statement Summary

Event is a nonterminal, declaration statement that occurs within Class statements and within the refactoring statement Migclass. It is also used within metalanguage class declarations and has some attributes that are only used in that context. Events are handled by user defined methods called "handlers". These handlers have names that are different from the event itself. In addition, the arguments associated with the event have a class name associated with them.

The attributes of the Event statement are as follows:

Attribute Description
Id This attribute is the identifier of the event. It must be unique within the scope of the class containing the event. The identifier is not case-sensitive.
NetHandler This attribute is the name of the event handler to be used in the authored code.
NetArgs This attribute is the name of the class to be associated with the arguments of the handler to be used in the authored code.
Status This attribute is the Status attribute as discussed on the Declaration page. It specifies the various context flags to be associated with the event.
NetName This attribute is the identifier of the event itself to be used when declaring or referring to it in the target language.
MigName This attribute is identical to NetName. If both are used in the declaration the Migname takes precedence.
MigStatus This attribute is a MigStatus attribute as discussed on the Declaration page. It contains generalized migration settings for the event.
MigComment This deprecated string attribute associates a comment with the event. This comment does not trigger the gmNI event handlers and can interfere with the MigStatus attribute.
MigPattern This string attribute associates a surface pattern string with code references to the event. See the Patterns page for details on the content of pattern strings. It is equivalent to the All pattern. Pattern strings associated with events supply code startup statements needed in the handlers of the events.
CshPattern This string attribute associates a surface pattern string with code references to the event. See the Patterns page for details on the content of pattern strings. It is equivalent to the Csh pattern. Pattern strings associated with events supply code startup statements needed in the handlers of the events.
VbnPattern This string attribute associates a surface pattern string with code references to the event. See the Patterns page for details on the content of pattern strings. It is equivalent to the Vbn pattern. Pattern strings associated with events supply code startup statements needed in the handlers of the events.
Npram This integer attribute specifies the number of parameters associated with the surface pattern strings.
Role This attribute contains an optional keyword describing the overall role of the operation being authored via the surface pattern strings: Unknown, Property, Method, Define, Utility, Command, Constant, Function, Event, Control, Collection, Resource, Index, or Migclass. The default is None.
Patstatus An optional keyword describing the overall status of the operation authored via the surface pattern strings: Ok, Delete, Deprecated, NotImplemented, MustCorrect, NotIdent, Postfix, or NeedsPren. The default is Ok.
Opcode This attribute is only used with metalanguage declarations. This entry specifies the actual opcode.subcode byte pair to be issued by references to the event as opposed to the normal call operations.

The declarations within the Event statement are as follows:

Substatement Description
Argument Defines one of the event arguments.

The script errors associated with the Event statement are as follows:

Error Description
1130 Method command missing required id attribute.
1131 Unable to store METHOD vector: %1d
1132 The syntax cannot be found.
1133 The subprogram type is undefined.
1134 Encountered following when expecting 'argument': %1d


 Constant Statement Summary

Constant is a terminal, substatement of the Class statement. It has no refactoring or declaration flags associated with it.

The attributes of the Constant statement are as follows:

Attribute Description
Id This attribute is the identifier of the constant. It must be unique within the scope of the class containing it. The identifier is not case-sensitive.
Type This attribute is a Type attribute as discussed on the Declaration page. It specifies the type of the constant. If omitted, String is assumed.
Value This required attribute contains the value associated with the constant.

The script errors associated with the Constant statement are as follows:

Error Description
1040 Constant command missing required id attribute.
1041 Unable to store constant vector: %1d
1042 Constant command missing required value attribute.


 Typedef Statement Summary

Typedef is a terminal, declaration statement that occurs only in description files authored from IDL-- i.e., external COM components. Its purpose is to supply an alternative identifier for a type. Typedefs are not moved forward into the authored code. Rather whenever a type specification is read, if it is a typedef, then the actual type is substituted.

The attributes of the Typedef statement are as follows:

Attribute Description
Id This attribute is the identifier of the typedef. It must be unique within the scope of the library containing it. The identifier is not case-sensitive.
Type This attribute is a Type attribute as discussed on the Declaration page. It specifies the type that will be associated with any component that defines its type using the identifier of this typedef.

The script errors associated with the Typedef statement are as follows:

Error Description
1055 Typedef command missing required id attribute.
1056 Unable to store typedef vector: %1d
1057 Typedef command missing required type attribute.


 gmPL Refactoring Statements

Within gmBasic many of the changes made to the code as it moves from its VB6/ASP source code form into its ultimate .NET target code form can most easily be formulated as refactoring operations. These include:
  1. Renaming symbols either to avoid clashes or to make them easier to maintain.
  2. Reauthoring a subprogram because its original approach is inappropriate or unworkable in the .NET environment
  3. Changing the type of a symbol which was either undefined or too weakly specified.
  4. Changing the status of a symbol to change its scope or behavior
  5. Changing the structure of a symbol to clarify its size and dimensionality.
  6. Removing a symbol because it is not needed or wanted.
  7. Changing logic flow and/or program operations to conform to new requirements.
  8. Replacing references to external libraries with references to native libraries
All of these operations involve manipulations of the symbol table and of the intermediate code produced. They do not directly reference the source or target code. The refactoring statements themselves are:

Statement Description of use
Refactor Introduces a set of refactoring statements
CallByName Changes symbol-related code events that yield CallByName late binding calls into direct boxed calls.
Extend Extends the content of a class by adding new components.
FixType Changes the binary type of a component or group of components
Implements Specifies that a VB6 class implements another class or interface.
MigClass Introduces a new class that contains related refactoring information used for complex migration operations, especially as related to designer code.
Migrate Specifies migration of a specific symbol introduced via an external library description.
Reauthor Replaces the content of a subprogram with a completely rewritten block of code
Remove Prevents a component from being authored
Rename Changes the authored name of components
Replace Replaces either the members of an external class or the patterns of opcodes via replacement declarations.

Within gmBasic the portation process proceeds in 8 steps:

  1. Loading the VB6/ASP source code.
  2. Fixing the VB6/ASP source code.
  3. Building the symbol table from the source code
  4. Compiling the source code into intermediate code
  5. Analysing the symbol table and intermediate code
  6. Authoring the target code from the intermediate code and symbol table
  7. Fixing the target code
  8. Deploying the target code
During this process there are 3 points at which refactoring operations can be made. First after step 3, which builds the symbol table. This is a very effective place to strengthen the specifications of the symbols so that the compiler can take advantage of this additional information while generating the intermediate code. Second after step 4 when the compiler has completed, but the code analyser has not yet run. This is an excellent time to introduce .NET types explicitly and to do any removals. Third after step 5, when the analyser has run, but before the author has executed. This is the best time to do symbol renaming and code reauthoring.

Refactoring tends to effect the entire code base. It is not intended to make individual changes in actual code. The source code fixing operations are intended for this. The rule of thumb for using a refactoring operation as opposed to a fix editing operation is that the specification for the final recipient of the change is a symbol as opposed to a line/block of code. In general, portation is an art and the selection of which approach to use will clearly vary by individual and application.

Whenever possible, refactoring should be done via "shallow" changes -- changes which are applied to the actual surface or source form of the code using the Fix statement. These shallow changes can be applied to both the source code before it is translated and to the target code after it is produced, but before it is published. Such changes are easy to visualize and to specify. Unfortunately many of the changes needed cannot be specified in this way -- refactoring is required.

 Refactoring Property Specifications

Many of the refactoring statements are used to deal with the transformation of the VB6 property specifications into .NET designer code. Much of the code within VB6 forms deals with controls. These controls all have complex sets of properties that must be initialized within the VB6 code. This initialization code contains nested sets of "name=value" pairs organized into nested blocks started off by BEGIN or BEGINPROPERTY statements and ending with END or ENDPROPERTY statements. Here is a simple example of such a specification.

 Begin VB.Form VB0001Form
    Caption         =   "VB0001"
    ClientHeight    =   5115
    ClientLeft      =   60
    ClientTop       =   345
    ClientWidth     =   5280
    LinkTopic       =   "Form1"
    ScaleHeight     =   5115
    ScaleWidth      =   5280
    StartUpPosition =   3  'Windows Default
    Begin VB.CommandButton Command1
       Caption         =   "Run VB0001 Test"
       Height          =   375
       Left            =   1440
       TabIndex        =   0
       Top             =   1320
       Width           =   1935
   End
 End
In the above, the Begin has the syntax "Begin controltype identifier" where controltype is a defined control type and identifier is the identifier of the control object in the user code that is being defined. In the name=value pairs the name is the name of a property defined for the control type class and the value is the value to be assigned to that property for the identified instance of the control type.

There are of course properties of controls that are themselves object types rather than simple value types. The most common of these is the Font property. Here is an example of a specification of this type.

 Begin VB.Label lblFirst
    Alignment       =   2  'Center
    BorderStyle     =   1  'Fixed Single
    Caption         =   "VB is fun"
    BeginProperty Font
       Name            =   "MS Sans Serif"
       Size            =   24
       Charset         =   0
       Weight          =   700
       Underline       =   0   'False
       Italic          =   0   'False
       Strikethrough   =   0   'False
    EndProperty
    Height          =   615
    Left            =   2040
    TabIndex        =   0
    Top             =   480
    Width           =   2655
 End
In the above the BeginProperty statement has the syntax "BeginProperty property" where property is the identifier of a property in the containing control type that has an object type. There is no additional identifier here because the values are part of the higher instance. BeginProperty is semantically equivalent to a simple name=value pair except that multiple values are being supplied.

All of the above is an oversimplification in every possible way. Even in the above "simplest of all examples", for example, the VB.Label control type does not have a property called Font; rather it has properties like FontName, FontSize etc. When the above syntax is extended to COM CONTROLS all formal relationships are ignored in every possible way. The specifications look like the above, but there truly are no real rules. Each COM property specification has to be examined carefully and converted into a specification that associates values with a set of user-defined controls in a consistent manner.

Converting the input property specifications into a consistent form is a difficult, but trivial problem when compared to the problem of reauthoring those specifications in .NET. The two primary problems are that in .NET controls are not nested, they have a linear structure and then there are later instructions that add children into the scope of the parents. How and when and with what adornments are needed to make these scope specifications vary widely. In addition in .NET some values are assigned to properties directly in the code and others are assigned via external resource files.

An important point to be remembered about the property specification code is that though it uses opcodes, though opcodes are not authored via a string-machine. It has code fragments in it that can be evaluated and viewed in the same way as procedural code, but it is used simply as a data-store for the information initially obtained from the VB6 specifications and then as changed to supply information to the .NET control author. New properties must be added, old properties must be removed or restructured or radically migrated. There are no dependable simplistic correspondences between properties defined for the classes and references to those properties. The goal is that the eventual authored .NET property specifications will accurately reflect the original intent of the VB6 source; however, that goal is achieved via the interaction of diverse components and not directly in the property code blocks.

 Refactor Statement Summary

Refactor is a nonterminal, refactoring statement that occurs in command scripts, in reference scripts called RefactorLibraries, and in the GlobalSettings file within RefactorFile statements. The term "refactoring" generally refers to changing the implementation of user code when porting it to a new platform; while, the term "migration" refers to reformulating references to and replacing external libraries whose source code is not part of the source code being ported. Within actual portation projects, however, this distinction becomes blurred. Both terms are used throughout this discussion.

There are three places within a command scripts that a Refactor statement can occur. First, it can occur as a substatement of the Compile statement. It is applied after the compiler has built the symbol table but before it has processed any procedural code. This is a very effective place to strengthen the specifications of the symbols so that the compiler can take advantage of this additional information while generating the intermediate code. Second, it can occur directly in the command script after the Compile statement but before the Analyse statement. This is an excellent time to introduce target types explicitly and to do any removals. Third, it can occur directly in the command script after the Analyse statement but before the Author statement. This is the best time to do symbol renaming and code reauthoring.

A RefactorLibrary is a reference script initially authored by gmBasic from an IDL file for an external library that is being reformulated. To do the reformulation the actual declarations can be modified, but this can make those modifications difficult to track. There is a refactoring statement Migrate that is primarily intended to modify the properties of external components. The choice of using Migrate versus making modifications to declarations is entirely up to the user of gmBasic. Regardless of the choice made, reformulating external libraries always requires that additional information be added to the reference script describing the intended .NET side of the external and the transformation path needed to get there. This information as well, is supplied by a refactor statement added to the bottom of the original gmBasic authored file. The normal convention is to keep the original gmBasic file in the selected System location and to store the RefactorLibrary file in the selected target location. The refactoring statements within a RefactorLibrary are applied at the time the reference script is read and can, therefore, only be applied to the components of that library. If the user wishes to leave the gmBasic authored files alone, then another alternative is available. After a reference script is read, its filename is modified to be preceded by Mig. to form the name of a possible refactoring file which contains the Refactor statements modifying the characteristics of its components. If found, the statements in that file are treated as though they had been physically at the end of the original file. When these Mig files are used, the original file is left in the System location and the Mig file is placed in the Target location.

RefactorFile is a nonterminal registry type that is stored in the globalsettings storage area. The RefactorFile source attribute specifies the full pathname of the file whose symbols are to be refactored. The actual Refactor statements then form the target text buffer.

<Registry type="RefactorFile" source="Pathname of file to be refactored" >
   <Refactor>
      refactor statements
   </Refactor>
</Registry>
The registry is checked once for a RefactorFile entry for each class, module, form, or ASP file after the symbols for that file have been loaded but before the code has been compiled. There is nothing special about the refactor statements themselves. They behave exactly the same as Refactor statements placed within a Compile statement for a code project containing the specified file. Thus, the entry
   <Registry type="RefactorFile" source="\code\vb6\CommonFunctions.cls" >
     <Refactor>
       <FixType identifier="SortCollection.aObject" type="Interfaces.Icbn_Compare" />
    </Refactor>
  </Registry>
in a selected global settings file is identical to the following in a translation script
   <Compile project="\code\vb6\VariousCommonFunctions.vbp" >
      <Refactor fileFilter="[\code\vb6\CommonFunctions.cls]">
          <FixType identifier="SortCollection.aObject" type="Interfaces.Icbn_Compare" />
      </Refactor>
  </Compile>
There is no equivalent of the post-compiler refactoring statements, using RefactorFile. These can only be placed in command scripts.

A final distinction that is made within the Refactor statement is that of the hostid versus the filefilter. Refactor statements all identify the components in the symbol tree that they are referencing via qualified identifiers -- a series of identifiers separated by periods. To find the identified component the logic begins with a base symbol and then checks the first identifier to see if it is a child of that base. If so, that child becomes the new base and the next identifier is checked until all identifiers in the series have been processed. The final child found is the component being referenced. At issue here is the initial base symbol to be used. The Refactor introduces two potential base symbols -- the hostid which is the external library whose components are the primary focus of the migration and/or the filefilter which is the user code file whose components are being refactored. The various refactoring commands are either hostid oriented or filefilter oriented depending upon their primary use.

The attributes of the Refactor statement are as follows:

Attribute Description
DllName This attribute specifies the name of a dll file that should be loaded when the refactor statement is processed and should remain loaded for the remainder of the current gmBasic execution. Up to 64 Dlls may be loaded at the same time.
Event This attribute is used to trigger a set of generic user migration code events within the analyser. These events are triggered first during the initialization phase and second during the code review phase for each code block in the current scope of the analyzer by references in the code to subcomponents that have a UserCode status flag set. The start of the string stored in the comment field of the component must match this attribute value to trigger the code events in the dll file.
Id This attribute is the hostid. It is the identifier of the library or project being refactored. Libraries are identified via their local filename enclosed in square brackets like [mso.dll] or [msword9.olb] or [mscomctl.ocx] or [msado20.tlb]. In this context fully qualified names, whose identifiers are separated by periods can also be used. The brackets are used to avoid confusion.
ErrorStatus This attribute controls the consequences of an error. If it is Ignore, then no message is displayed and the tool simply continues. If it is Warning, then a message is displayed and the and then to tool continues. If it is Error, then a message is displayed, and an abnormal exit to the operating system is taken. The default setting for this attribute is Error.
FileFilter This attribute is the fully qualified identifier of the user code file whose components are being refactored. It specifies the filefilter for the following refactoring statements.

The declarations within the Class statement are as follows:

Substatement Description
Fixtype This filefiler oriented statement changes the binary type of a component or group of components
CallByName This filefilter oriented statement changes symbol-related code events that yield CallByName late binding calls into direct boxed calls.
Implements This filefilter oriented statement specifies that a VB6 class implements another class or interface.
Remove This filefilter oriented statement prevents a component from being authored.
Migrate This hostid oriented statement specifies migration of a specific symbol within an external library.
Rename This filefilter oriented statement changes the authored name of components.
Reauthor This filefilter oriented statement replaces the content of a subprogram with a completely rewritten block of code
Extend This hostid oriented statement extends the content of a class by adding new components.
Replace This hostid oriented statement replaces either members of an external class or the patterns of opcodes via replacement declarations.
Migclass This hostid oriented statement defines a collection of related refactoring information used primarily to describe the components on the .NET side of the migration.
Gmsl This command statement enters a gmSL subprogram that is needed in the authoring of the refactored code.
Reference This command statement loads a reference script defining and external library whose components are being referenced within the refactoring block.

The script errors associated with the Refactor statement are as follows:

Error Description
1102 Encountered illegal REFACTOR directive %1d


 CallByName Statement Summary

CallByName is a terminal, refactoring statement that occurs only within a Refactor statement. The refactoring done by this statement takes a different view of refactoring, since it is not symbols that are being refactored but rather symbol-related code events that must be trapped and then refactored. In particular, before the compiler generates a late-binding callbyname operation on a symbol it checks if that symbol has a CallByName refactoring boxing type associated with it. If so, it boxes the symbol to that type and attempts to perform a normal early-bound call. Removing CallByName is performed by the compiler and not by the analyser.

As discussed in the "Anatomy of CallByName" the alternative way of removing late-binding is to strengthen the type of the host symbol or to use the newer .NET type Dynamic. CallByName refactoring is used when changing the type of a symbol is not workable or desirable.

The attributes of the CallByName statement are as follows:

Attribute Description
Source This optional attribute specifies the component whose code is generating late-bound calls by name. If the containing Refactor statement had a FileFilter specified then this identifier should be specified relative to it; else it should be specified relative to the root of the symbol table. If this attribute is omitted, then the code source is assumed to be the parent of the host symbol.
Host This required attribute specifies the host symbol, the actual object instance that is exposing the method or property being called. If the containing Refactor statement had a FileFilter specified then this identifier should be specified relative to it; else it should be specified relative to the root of the symbol table. There are three special identifiers that can be used at the start of this attribute: *Project, *Item, and *Dim.identifier.
BoxType This required attribute contains a comma-delimited list of the boxing types that may be used to resolve the late binding. gmBasic checks each type entry to see if it has a component that matches the following method or property name. If none exists, it does a box to the last type in the list regardless of whether it still generates a late-binding. There are three special identifiers that can be used with the type entries: *None, *Project, and *Self.
Context This optional attribute specifies the context in which the late call can occur: LateCall, LateCollection, and LateDefault.

The special identifier *Project says to start the symbol search with the parent of the FileFilter. This will be the project file containing file whose symbols are being refactored. There are many different types of collections, the *Item identifier specifies any collection class Item method. The *Dim.identifier is necessary because these specifications are processed before any procedural code has been processed; therefore, undeclared variables are not yet in the symbol table. The *Dim simply specifies that the identifier needs to be declared. The *None type is used while these specifications are being developed. Where late calls are being generated is easy to see, but how to box them can be difficult to determine, especially if an interface has to be developed. The *None tells gmBasic to simply ignore the specification. The *Self type simply refers to the class being defined by the FileFilter code.

The default context is LateCall. Before the compiler produces a late-binding for a weakly-typed host it checks for a CallByName entry and attempts to resolve the LateCall via a boxing operation.

The LateCollection context occurs when nested Item().Item() references occur. For example consider the following situation

 Collection PeriodsCollection;
 PeriodInfo = new Scripting.Dictionary();
 PeriodsCollection.Add(PeriodInfo);
 StartUpString = PeriodCollections(index)("StartUp")
The statement
  <CallByName source="methodname" host="methodname.PeriodsCollection"
              context="LateCollection" boxType="Scripting.Dictionary" />
tells the compiler that the host to be boxed to Scripting.Dictionary is not PeriodsCollection itself, but rather PeriodCollections.Item()".

The LateDefault context singles out subprogram arguments for which unwanted default properties are being propagated. In the line of code

   recordSets.Add("recordset1",myRecordSet)
recordSets is built as a collection, Scripting.IDictionary of recordsets. Its Item is simply typed as variant which means that in Vb6 it expects default property propagation. The default property of a RecordSet is Fields so the above ends up being translated as
   recordSets.Add("recordset1",myRecordSet.Fields)
This context introduces the third type of CallByName refactoring: LateDefault. The actual command goes as follows
   <CallByName source="recordSets" host="Scripting.IDictionary.Add.Item"
               boxType="ADODB.Recordset" context="LateDefault" />
The way the gmBasic compiler works, it only generates a default property during a method call when the parameter is weakly typed as an Object or Variant. In this case that parameter is "Scripting.IDictionary.Add.Item". There are instances when codes pass default properties to this parameter, but in this case the code is passing an object instance of type ADODB.RecordSet itself. The VB6 system makes these decisions at runtime and thus is able to distinguish the two cases. The gmBasic compiler needs to be told that when passing arguments to the Add.Item parameter in the scope of "recordSets" treat that parameter as though it were strongly typed. Its semantically like a Boxing operation, but since passing a stronger type to "Object" requires no Boxing instruction, none is generated.

 The Anatomy of CallByName

Both .NET and VB6 support a CallByName method which is used at runtime to get a property, set a property, or invoke a method. In .NET its parameters are as follows:

Parameter Description
--------- ------------
ObjectRef A System.Object that is the host of the call. It is the instance of an object exposing the named property or method
ProcName A string expression containing the name of the property or method on the object that is being referenced.
UseCallType A CallType enumeration entry that specifies the type of procedure being called: Method, Get, or Set
Args() An optional System.Object array, ParamArray, containing the arguments to be passed to the property or method being called.

The VB6 form of this method is almost identical except for the UseCallType parameter which in VB6 is: VbLet, VbGet, or VbMethod. The following three Vb6 CallByNames

   CallByName Text1, "MousePointer", VbLet, vbCrosshair
   Result = CallByName(Text1, "MousePointer", VbGet)
   CallByName Text1, "Move", VbMethod, 4000, 4000

become the following in C#

using VBNET = Microsoft.VisualBasic;
  ...
   VBNET.Interaction.CallByName(Text1,"MousePointer",VBNET.CallType.Set,
                                 new object[]{System.Windows.Forms.Cursors.Cross});
   Result = VBNET.Interaction.CallByName(Text1,"MousePointer",VBNET.CallType.Get,
                                          new object[]{});
   VBNET.Interaction.CallByName(Text1,"Move",VBNET.CallType.Method,
                                new object[]{4000,4000});
In VB6, however, doing explicit CallByName is not required to achieve late-binding and in fact is rarely used. The compiler will generate these calls from equivalent weakly bound references. The following Vb6 statements
 Dim Text2 As Variant
 Text2.MousePointer = vbCrosshair
 Result = Text2.MousePointer
 Text2.Move(4000,4000)
produce the equivalent result in VB6 but in .NET the late binding must still be explicit.
  object Text2 = null;
  VBNET.Interaction.CallByName(Text2,"MousePointer",VBNET.CallType.Set,
                               new object[]{System.Windows.Forms.Cursors.Cross});
  Result = VBNET.Interaction.CallByName(Text2,"MousePointer",VBNET.CallType.Get,null);
  VBNET.Interaction.CallByName(Text2,"Move",VBNET.CallType.Method,
                               new object[]{4000,4000});
The focus of the CallByName statement is to return translations like the above into direct calls by inserting a boxing operation that specifies at compile-time the assumed type of the host symbol.

Recent .NET releases have introduced an explicit type Dynamic which allows code like the VB6 to be written. This type is supported by gmBasic via its FixType refactoring statement. In fact the above could be removed by a simple FixType to TextBox. There are complex situations where these direct solutions are either not workable or inappropriate such as with members of collections where the collection member type is not easily changed. The CallByName refactoring statement uses a boxing operation around the host symbol to avoid having to change any declarations. In this case, the following expansion of the translation command script

   <Compile Project="C:\gmSrc\GMTest\vb6test\VB0005\vb6\VB0005.vbp" >
      <Refactor FileFilter="C:\gmSrc\GMTest\vb6test\VB0005\vb6\VB0005.frm">
         <CallByName source="Command1_Click" Host="Command1_Click.Text2" BoxType="TextBox" />
      </Refactor>
   </Compile>
produces the following translation
   ((System.Windows.Forms.TextBox)(Text2)).Cursor = System.Windows.Forms.Cursors.Cross;
   Result = ((System.Windows.Forms.TextBox)(Text2)).Cursor;
   ((System.Windows.Forms.TextBox)(Text2)).SetBounds(4000,4000,0,0);
In the simple case presented above, the .NET CallByNames will behave in exactly the way they did in VB6. There are even instances where the .NET CallByName translation is the desired one. It is when the ProcName parameter becomes complex that real problems emerge. Consider this translation produced for a VB6 statement
   frm.txtFieldData(i).Text = vbNullString
      where frm is Variant
   VBNET.Interaction.CallByName(frm,"txtFieldData(i).Text",VBNET.CallType.Set,
                                new object[]{VBNET.Constants.vbNullString});
In .NET the ProcName must be a simple identifier. The translation correctly shows the intent of the VB6 and will even build in .NET, but it will throw an exception at execution time.

 Extend Statement Summary

Extend is a nonterminal, refactoring statement that occurs only in hostid oriented Refactor statements. Its purpose is to add properties to control classes needed to process property bag code. It can also be used to mirror coclasses in libraries.

The attributes of the Extend statement are as follows:

Attribute Description
Id This attribute is the identifier of the class or coclass which is the focus of the extend operation. It is expressed relative to the Id attribute of the parent Refactor statement. It must identify a class or coclass within the hosting library.

The substatements of the Extend statement are as follows:

Substatement Description
Property A declaration statement that declares a property to be added to the class identified by the statement. Any valid Property declaration may used.
Coclass A terminal substatement of the Extend statement that extends the library with a new coclass with a different Id but with the same subclasses.

The script errors associated with the Extend statement are as follows:

Error Description
1101 Extend identifier [%1d] is not defined.

The primary use of Extend is to add properties to control classes to satisfy references in the form property bag specification. By default the gmBasic VB6 property bag processor assumes that the names included with BeginProperty statements and on the left-hand-side of name=value are the names of properties of the containing control class. In the absence of any additional specification, when the processor encounters a name that it cannot identifier it triggers an "UndefinedProperty"condition. The Select UndefinedProperties attribute is used to control the treatment of this condition. Consider, for example, a simple code using the unmigrated mscomctl.ocx set of controls with undefinedproperties="warn".

WARNING#5403: Filename <\ImageList\vb6\Form1.frm>
   Property <NumButtons> not recognized
   Record:          NumButtons=   5
WARNING#5403: Filename <\ImageList\vb6\Form1.frm>
   Property <Images> not recognized
   Record:       BeginProperty Images {2C247F25-8591-11D1-B16A-00C0F0283628}
Regardless of whether a warning is issued or ignored the statement or the property block for undefined properties is then skipped. Assuming that skipping these specifications is not desirable the simplest way to deal with them is to simply add the missing properties to the relevant control class. Since the identifiers are not defined, there will be no references to them in the real code, so no harm is done. The refactoring Extend statement adds properties to a control. As an example
 <Extend id="IImageList" >
    <Property id="Images" type="ListImages" />
 </Extend>
 <Extend id="IToolbar" >
    <Property id="NumButtons" type="integer" />
 </Extend>
The id attribute is the identifier of the class that is to be extended. It can be fully-qualified in the same manner as other identifiers within a refactoring specification. Even here great care must be taken. Properties are contained in classes, while controls in OCX's are usually coclasses, which contain multiple classes. The Property statements themselves are completely standard. The properties added with the Extend statement behave exactly like the original ones and can be referenced later by other refactoring statements and migclasses.

 Coclass Extend Substatement Summary

Coclass is a terminal substatement of the Extend statement. It can be used if and only if the Id attribute of the parent Extend identifies a coclass. The statement adds a second coclass to the host library with the same subclasses as the host coclass but with a different identifier.

The attributes of the Coclass substatement are as follows:

Attribute Description
Id This attribute is the identifier of a new coclass to be added to the parent library that will match the host coclass.

As an example, instances of the Button coclass of the MSCOMCTL.OCX can be migrated to either to .NET ToolStripButton or ToolStripSeparator. The actual choice depends upon the properties of the instance, but the first step is to create a second coclass Separator that can be used to anchor the new references. Assuming that the original declaration of Button was

   <coclass id="Button" creatable="off" role="control" >
      <subclass id="IButton"/>
   </coclass>
Then this refactoring statement
   <Extend id="Button" >
      <Coclass id="Separator" />
   </Extend>
does the same thing as adding this declaration to the original reference script
   <coclass id="Separator" creatable="off" role="control" >
      <subclass id="IButton"/>
   </coclass>


 FixType Statement Summary

FixType is a terminal, refactoring statement that occurs within Refactor statements. It changes the binary type of a component. It can also be used to change various status or process flags associated with that component.

The attributes of the FixType statement are as follows:

Attribute Description
Identifier This required attribute specifies the symbol, the actual component whose type and/or flags are to be changed, If the containing Refactor statement had a FileFilter specified then this identifier should be specified relative to it; else, it should be specified relative to the root of the symbol table
Type This optional attribute is a Type attribute as discussed on the Declaration page. It specifies a new type of the identified component.
Status This optional attribute specifies that certain context, status, or process flags as specified on Declaration page be set for the identified components.

The actual entries that may be used for the Status attribute are as follows:

Entry Description
Overload This entry is only used with subprograms. It specifies that the subprogram should be overloaded. It actually marks the subprogram and all its optional arguments with the Overload context flag.
Protected This entry is only used with subprograms. It sets the Protected context flag which specifies that the component requires the protected adornment when it is declared in the target language.
BlockTemps This entry is only used with subprograms. It sets the BlockTemps process flag which blocks the formation of a TempArg when converting a Select into an If.
objectOnly This entry applies to components whose type is being set to Variant or Object. It sets the ObjectOnly process flags which blocks all type inferences on the component. It will retain its weak type and casting or boxing operations will be inserted where needed around references to the component.
Out This entry sets the ByOut context flag.
ByRef This entry sets the ByRef context flag.
ByVal This entry sets the ByVal context flag.

The script errors associated with the Fixtype statement are as follows:

Error Description
1093 Unable to resolve type [%1d] at this time.
1094 Unable to resolve status [%1d] at this time.


 Implements Statement Summary

Implements is a terminal FileFilter oriented refactoring statement that only occurs within Refactor statements. This external Implements statement is processed in the same way as Implements commands in CLS files are processed by gmBasic. It specifies that the class be refactored to implement the interface defined by the class specified with this statement. There are, of course, differences in the naming conventions. For Refactor Implements the names of components satisfying the interface must match exactly as opposed to being preceded the class name and an underscore.

The attributes of the Implements statement are as follows:

Attribute Description
Interface This attribute contains the identifier of the class whose interface is being implemented by the class identified in the FileFilter attribute of the parent Refactor statement.

Though at a superficial level VB6 interfaces appear to be the same as those in the established OOPs, there are several very important differences. First of all, any class can serve as an Interface for another class. An interface class is created in the same manner as any other class. It is this fact that makes this refactoring statement possible. The significance of this is that gmBasic does not need know that a given class is an interface until some other class implements it. Second of all, VB does not support "implementation inheritance", it supports "interface inheritance". What this really means is that a Vb6 class that is used later as an interface can contain not only implementation logic which is only used if an object of that class is created, but the class can contain other components as well which are not part of the interface. The explicitly "Public" methods and properties of the interface class are what must be implemented, but it is not even necessary for the component types to correspond directly as the following working VB6 code shows.

   Attribute VB_Name = "PersonalData"
   Public Name As String
   Public Address As String

   Implements PersonalData
   Private Property Get PersonalData_Address() As String
      PersonalData_Address = "SupplierAddress"
   End Property
   Private Property Let PersonalData_Address(ByVal RHS As String)
   End Property
   Private Property Let PersonalData_Name(ByVal RHS As String)
   End Property
   Private Property Get PersonalData_Name() As String
     PersonalData_Name = "SupplierName"
   End Property
Components defined as fields in the interface file are implemented as properties. Note also if the interface had been asserted via the refactoring statements, the above properties would be assumed to have the simpler identifiers -- Name and Address.

 Migclass Statement Summary

Migclass is a nonterminal, refactoring statement that occurs within the scope of a HostId oriented Refactor statement, but also within command scripts and language files. This statement introduces a new class that contains related refactoring information used for complex migration operations, especially as related to designer code.

The attributes of the Migclass statement are as follows:

Attribute Description
Id This attribute is the identifier of the migration class. It must be unique within the scope of its parent, which is the hostid if the statement is within a Refactor, else it is the root. It is not case sensitive.
Parent This attribute specifies the "parent" of the migration class. In this content "parent" refers to the external class whose components the migration class is intended to enhance or describe. This is usually an external library being migrated or a VB6 language class to be authored.
MigName This attribute supplies the name to be used when for the migration class in the target translations.
needsinit This is a On/Off flag attribute. The On setting sets the Needsinit status flag On which means that the class needs to be initialized by the author when declared.
NetName This attribute supplies the name to be used when for the migration class in the target translations. It differs from MigName in that it also sets the External status flag On. This means that the class is external to the library in the target implementation to which it was assigned in the source implementation. Therefore, when authoring the identifier of the class do not precede it with its source parent membership information.
Creatable This is an On/Off flag attribute. The Off setting sets the Noncreatable status flag On. It means that the migration class objects cannot be created. When declaring objects of this class simply NULL them as opposed to using new to create an instance.

The declarations within the Migclass statement are as follows:

Substatement Description
Property Declares a property within the migration class
Field Declares a field within the migration class
Method Declares a method within the migration class
Enumeration Declares an enumeration within the migration class

The script errors associated with the Migclass statement are as follows:

Error Description
1089 Migclass command missing required id attribute.
1090 Unable to store MIGCLASS LIB_COMP vector: %1d
1091 Unable to find parent CLASS: %1d
1092 Encountered following when expecting class component: %1d


 Migrate Statement Summary

Migrate is a terminal, refactoring statement that occurs within hostid oriented Refactor statements. It specifies the migration of a specific symbol introduced via an external library description file. The Migrate command is by far the most complex command within a refactoring specification. Though the use of separate migration files, as opposed to simply changing the description file being migrated, complicates the notation, it is being retained not only for use with external libraries, but also for use within translation scripts and to migrate user code.

The attributes of the Migrate statement are as follows:

Attribute Description
Id This attribute specifies which component in the library or projectfile being refactored is the receive the specified changes. If the attribute is omitted that the library or projectfile specification itself is to be changed.
MigComment This deprecated string attribute associates a comment with the component. This comment does not trigger the gmNI event handlers and can interfere with the MigUserCode attribute.
Overrideuser This is an On/Off flag attribute. The On setting sets the Overrideuser status flag On. For components that are used to satisfy implementation requirements, this flag forces the component to have the attributes as specified in the interface as opposed to as specified in the user code.
Overridecall This attribute applies only to classes and coclasses and the only setting recognized is on. It is used with those classes whose migrated reference class is being split; thus, the analyser should not insert type casts when it sees what appear to be type violations associated with this class.
Canbenull This is an On/Off flag attribute. The On setting sets the CanbeNull status flag On. This means that checks of the component's value for being empty can be Null as well. References to them in the intermediate code have to be checked if they are Null or Empty.
MigPattern This string attribute associates a surface pattern string with code references to the component. See the Patterns page for details on the content of pattern strings. It is equivalent to the All pattern.
CshPattern This string attribute associates a surface pattern string with code references to the component. See the Patterns page for details on the content of pattern strings. It is equivalent to the Csh pattern.
VbnPattern This string attribute associates a surface pattern string with code references to the component. See the Patterns page for details on the content of pattern strings. It is equivalent to the Vbn pattern.
Npram This integer attribute specifies the number of parameters associated with the surface pattern strings.
Role This attribute contains an optional keyword describing the overall role of the operation being authored via the surface pattern strings: Unknown, Property, Method, Define, Utility, Command, Constant, Function, Event, Control, Collection, Resource, Index, or Migclass. The default is None.
Patstatus An optional keyword describing the overall status of the operation authored via the surface pattern strings: Ok, Delete, Deprecated, NotImplemented, MustCorrect, NotIdent, Postfix, or NeedsPren. The default is Ok.
Reftype Within a class there are three non-constant component types -- property, method, and accessor. The manner in which these components are referenced in the source code depends upon what type of component they are. This attribute changes this reference type to one of the above three. Obviously, great care must be taken in the use of this attribute. Note that when properties are being converted to methods this attribute also sets the CallPattern migration status flag. Simply stated the CallPattern flag, if set, indicates that the pattern specifies how the symbol is used as opposed to identified.
Status This attribute applies only to library class components like property, method, and accessor. It is used to set its status flags and must contain one of the entries from the PropertyStatus enumeration. This attribute completely replaces any other status flags set for the indicated component.
Type This attribute only has meaning if the identified migration component is a property, method, accessor, argument, or coclass. For coclasses the type specification literally changes them into TypeDefs. For the other components it changes their binary type information.
MigName This attribute changes the migration name of the component. It may be used with any component. The migration name is the name the author uses when it displays the identifier of this component. It does not effect the identifier of the component in so far as references to that component are concerned. In addition, to setting the name, this attribute also turns off the External and ActiveX migration status flags.
Static This is a On/Off flag attribute. The On setting sets the External status flag On. This means that the class is external to the library in the target implementation to which it was assigned in the source implementation. Therefore, when authoring the identifier of the component do not precede it with its source parent membership information.
Appobject This identifier attribute sets the AppObject status flag on and stores the identifier in the description table of the component. It means that the component is an application wide singleton object which requires that special AppObject code be authored for it.
Libtype This attribute changes the changes library type. It may only be used with Library components. This is an entry from the LibraryType enumeration.
MigStatus This attribute has meaning for all components. Its purpose is to turn on one of the component status flags as listed on the Declaration page.
Location This attribute only has meaning if the identified migration component is a library. In this case the location string for that library is replaced by the supplied attribute value. The most commonly used replacement value is DoNotDeclare which tells the project file author not to include a reference to this library.
MigUsercode This attribute is used to trigger a Code event in a migration dll. The first token of the attribute string must match the event attribute value specified for a migration dll. Any additional tokens are optional and are processed by the event handler itself.
Creatable This is an On/Off flag attribute. The Off setting sets the Noncreatable status flag On. It means that the component class objects cannot be created. When declaring objects of this class simply NULL them as opposed to using new to create an instance.
Casttype This attribute applies only to classes and coclasses and the only setting recognized is off. It is used with those classes whose migrated reference class is being split; thus, the analyser should not insert type casts when it sees what appear to be type violations associated with this class.
NetHandler This attribute is the name of the event handler to be used in the authored code.
NetArgs This attribute is the name of the class to be associated with the arguments of the event handler to be used in the authored code.
BoxTypes This attribute only applies to library components. It specifies a comma delimited list of possible types that this component may contain.
Optional This attribute specifies that the component is an optional argument and specifies the value to be used if the argument is omitted. The Argument page contains a description of the valid entries here.
ZeroBased This is an On/Off flag attribute. The On setting sets the ZeroBased process flag On. It is used by the analyser to decrement subscripted references to components with this flag set.
IsDbNull This is an On/Off flag attribute. The On setting sets the IsDbNull status flag On. The component is a class whose instances should be checked against DbNull as opposed to Null.
Propertybag This is an On/Off flag attribute. The On setting sets the Propertybag process flag On. This attribute tells the property bag processor of to look for BeginProperty and NameValue pairs for this component.
Axlocation This string attribute applies to external libraries only. It is used for IDL authored ActiveX libraries that are to be used as COM components. It declares the pathname of the AxInterop library.
Removeresumenext This is an On/Off flag attribute. The On setting sets the Removeresumenext process flag On. This attribute tells the analyser to turn off the "On Error Resume Next" to try-catch conversions for a particular subprogram. The algorithms used here are fairly robust, but can never be perfect. Specific codes may well encounter problems that are best dealt with by simply turning the algorithms off.
Removeonerrorgoto This is an On/Off flag attribute. The On setting sets the Removeonerrorgoto process flag On. This attribute tells the analyser to turn off the "On Error Goto" to try-catch conversions for a particular subprogram. The algorithms used here are fairly robust, but specific codes may well encounter problems that are best dealt with by simply turning the algorithms off.

The script errors associated with the Migrate statement are as follows:

Error Description
1097 Migrate identifier [%1d] is not defined.


 Reauthor Statement Summary

Reauthor is a nonterminal, refactoring statement that occurs only within a Refactor statement. It replaces the authored content of a subprogram with a hand written block of code

The attributes of the Reauthor statement are as follows:

Attribute Description
Subprogram This required identifier attribute specifies the subprogram whose authored content is to be replaced. If the containing Refactor statement had a FileFilter specified then this identifier should be specified relative to it; else, it should be specified relative to the root of the symbol table.

The script errors associated with the Reauthor statement are as follows:

Error Description
1096 Unable to find subprogram [%1d] in project.

An example of this statement from the FMSTOCKS sample is shown below.

 <Analyse/>
 <Refactor>
 <Reauthor subprogram="FMStocks_DB.GetComputerName"><![CDATA[
 public static string GetComputerName()
 {
    return System.Environment.MachineName;
 }
 ]]></Reauthor>
 </Refactor>
Note that the Refactor statement introducing it follows the Analyse statement. This is not required, but is a suggested convention.

 Remove Statement Summary

Remove is a terminal, refactoring statement that occurs only with a Refactor statement. It prevents a component from being authored. For components other than subprograms, removing them involves simply not declaring them in the target code. For subprograms, they can either not be declared or they can be stubbed out --.i.e. declared but no procedural code authored. The problem with not declaring components is that their references in the procedural code must be dealt with as well. The bulk of the attributes associated with this statement deal with the issue of replacing references to the undeclared components.

The attributes of the Remove statement are as follows:

Attribute Description
Identifier This required identifier attributes specifies the component to be removed. If the containing Refactor statement had a FileFilter specified then this identifier should be specified relative to it; else, it should be specified relative to the root of the symbol table.
MigPattern This string attribute contains a pattern string that will be used as a substitute for a reference to the component. Any arguments that reference might require have to be accounted for in the pattern string. See the Patterns page for details.
MigStatus This attribute is one of the entries -- Notimplemented, Delete, Stubout, or a code event string.
MigComment This attribute supplies a string that is substituted for references to the component.

The script errors associated with the Remove statement are as follows:

Error Description
1098 The identifier [%1d] could not be found.


 Rename Statement Summary

Rename is a terminal, refactoring statement that occurs only with a Refactor statement. It changes the authored name of a component.

The attributes of the Rename statement are as follows:

Attribute Description
Identifier This required identifier attribute specifies the component to be renamed. If the containing Refactor statement had a FileFilter specified then this identifier should be specified relative to it; else, it should be specified relative to the root of the symbol table.
Content This required identifier specifies the name to be used for the component in the target code.
Status This attribute is deprecated. If the component is a variable and if this attribute is supplied any value, then the context flags Static and Private are set for it.

The script errors associated with the Rename statement are as follows:

Error Description
1095 Unable to find identifier [%1d] in project.


 Replace Statement Summary

Replace is a nonterminal, refactoring statement that occurs only with a Refactor statement. It is used to replace components in an external library class or to replace language surface patterns in a language file.

The attributes of the Replace statement are as follows:

Attribute Description
Id This required attribute either contains the entry Patterns or it contains the identifier of an external library class. If the containing Refactor statement had a HostId specified then this identifier should be specified relative to it; else, it should be specified relative to the root of the symbol table.

The script errors associated with the Replace statement are as follows:

Error Description
1099 Replace identifier [%1d] is not defined.
1100 Replace identifier [%1d] is not a class.

If patterns are being read, then the substatements of the Replace are the same as those of the Patterns statement and are processed in the same manner except that existing patterns are replaced rather than new patterns being defined. See the Patterns page for details.

If a library class is identified, then the substatements of the Replace are the same as those of the Class statement and are processed in the same manner except that existing declarations are replaced rather than new declarations being defined. See the Class page for details.

 gmPL Metalanguage Statements

The gmPL Metalanguage statements define the intermediate language file vb7Lang that organizes the conversion of source language statements into target language statements.

A language definition includes library components as well as language components. The library components are described within the Declaration pages. The language statements described here are as follows:

Statement Description of use
Language This statement begins a language definition. There is only one language declared, Basic as used by gmBasic.
Default This statement is used to specify default control properties that are ultimately to be authored in the designer code.
Messages This statement supplies the actual text of the messages displayed. They are identified within gmBasic by a simple number.
Opcodes This statement associates identifiers with the numeric operation codes that specify the basic operations performed within the intermediate language.
Patterns This statement initiates the definition of surface patterns for the operation codes in the intermediate language.
Statements This statement is used to specify which statements are available in the language and what the attributes are of those statements. In this context, the languages defined are not the source language, VB6, but the internal languages used by gmBasic.
Types This statement supplies names for the native types used by gmBasic, followed by the simple enumerated types that are used to specify the various classifications required by the language description.

With the possible exception of the surface patterns, messages, and some of the enumerated types the entries in the language file should not be changed. The discussion here is intended to describe the language specification. The gmBasic tool itself aggressively uses the language information tables to control its operations. It is not, however, driven by them. The primary purpose of the language file is to act as a data store for gmBasic which expects that data to be present in its presently defined form.

 Language Statement Summary

Language is the primary statement that controls a language definition. The language statement occurs within a command script whose startup tag is Metalanguage. When gmBasic encounters a command script with the Metalanguage startup tag in suspends its normal operation in expectation of processing its language definition. The standard language specification file starts as follows
   <MetaLanguage>
      <Include Filename="Messages.xml" />
      <language id="Basic" >
        ...
The messages file contains a Messages statement which defines the error messages used by gmBasic when it processes statements, including its own language definition. The language statement must be preceded by the Messages statement, but may not be preceded by any other statement. The final output of the Metalanguage command script is a virtual binary information file called vb7lang.vbi which must be stored in the home directory of gmBasic which, by default, is the directory that contains the actual executable file. See the gmCL discussion for details on controlling how gmBasic starts up.

The attributes of the Language statement are as follows:

Attribute Description
Id This required attribute is the identifier of the language being defined. gmBasic requires a definition identifier of Basic.

The substatements of the Language statement are as follows:

Substatement Description
Select This is a standard Select statement as described on that page; however, it has one important difference. The attribute settings are saved in the language file and are used to set the default values of those attributes on all subsequence uses of gmBasic.
Library This is a standard Library declaration used to define an external set of classes for the internal scripting language gmSL. The library is called gmSLang.dll. The actual implementation of these classes is internal to gmBasic. The pages under gmSL describe this language and its classes.
Class This is a slightly enhanced version of the Class statement that references the operation codes. These enhancements are described in the declaration description pages for the various class components. The classes defined are the built in classes of the VB6 language and its various control class extensions.
Enumeration This is a slightly enhanced version of the Enumeration statement that references the operation codes. These enhancements are described on the Enumeration page.
Opcodes This statement associates identifiers with the numeric operation codes that specify the basic operations performed within the intermediate language. It is these identifiers that are used to refer to those operations in the language definition.
Default This statement is used to specify default control properties that are ultimately to be authored in the designer code.
Patterns This statement initiates the definition of surface patterns for the operation codes in the intermediate language.
Statements This statement is used to specify which statements are available in the language and what the attributes are of those statements. In this context, the languages defined are not the source language, VB6, but the internal languages used by gmBasic.
Types This statement supplies names for the native types used by gmBasic, followed by the simple enumerated types that are used to specify the various classifications required by the language description.

The script errors associated with the Language statement are as follows:

Error Description
1064 Language command missing required id attribute.
1065 Unable to store Language id: %1d
1066 The following record is not recognized: %1d


 Default Statement Summary

Default is a nonterminal, metalanguage statement. It is used to specify default control properties that are ultimately to be authored in the designer code. They are saved by this statement and then read into the back of code storage by the analyser so that they will be picked up, if there is no setting for the property in the actual code.

The attributes of the Default statement are as follows:

Attribute Description
Id The identifier of the control type for which default property setting values are to be supplied.
Lang The designer code language for which the setting values are to be used.

The declarations within the Default statement are as follows:

Substatement Description
Setting This substatement specifies and actual setting to be used.

The attributes of the Setting substatement are as follows:

Attribute Description
Id The identifier of the property of the control type for which a setting value is being specified. Note that Font properties are specified as "Font.fontProperty"
Value The actual default value to be associated with the property. Note that these value often contain special characters that are toxic to Xml so the value may alternatively be specified as text associated with the setting as shown below. When this alternative is used, the entire specification must be on a single line.
<setting id="BackColor"><![CDATA[&H80000005&]]></setting>

The script errors associated with the Default statement are as follows:

Error Description
1031 Default command missing required id attribute.
1032 The indicated control [%1d] has no class information.
1033 Encountered following when expecting 'setting': %1d
1034 Setting command missing required id attribute.
1035 Setting command missing required value attribute.
1036 Font Property [%1d] not recognized
1037 Property [%1d] not recognized


 Messages Statement Summary

Messages is a nonterminal, metalanguage statement that can only be used within MetaLanguage command scripts as the first statement in that script. In particular, it must precede the Language statement itself. The Messages statement defines the error messages used by gmBasic when it processes statements, including its own language definition.

The Messages statement has no attributes.

The substatements of the Messages statement are as follows:

Substatement Description
Message This substatement defines an individual message for a specified message number.


 Message Substatement Summary

Message is a terminal, metalanguage substatement that occurs within the Messages statement. This substatement defines a message to be associated with a message number used by gmBasic when it needs to display it. The numbers of the messages may not be changed, but their text may be.

The attributes of the Message substatement are as follows:

Attribute Description
Id This integer attribute is the numeric identifier of the message desired by gmBasic. These messages are classified in numeric ranges as described below.
Text This string attribute contains the actual message to be associated with the number. Many of the messages have parameters that are to be included in the messages. These are placed in the message text as "%nd" or %nv" when "n" is the parameter number and "d" means a string value and "v" means an integer value.

The actual messages can be found in the file Messages.xml. Their general characteristics are discussed here.

Messages in the 100 to 200 range are simple process/informative messages that typically have one or two external strings (%1d,%2d) or values (%1v, %2v) associated with them. They are all handled by the simple message handler methods and have no preamble messages associated with them.

Messages in the 1001-1999 range are gmSL syntax errors and general scripting problems. Message 1000 is the preamble message for these errors. By convention:

Param Description
%1v is the error number itself, also the message number
%1d is the optional string passed to the message handler
%2d is the name of the Xml file being processed

Messages in the 2001-5999 range are VB6 syntax warnings. Message 2000 is the preamble message for these warnings. By convention:

Param Description
%1v is the warning number itself, also the message number
%2v is the statement number in the source file
%3v is the starting character position of the error
%1d is the Source filename
%2d is the last encountered token string
%3d is the source record beginning at the point the error was detected

Messages in the 4001-4999 range are IDL syntax errors. Message 4000 is the preamble message for these errors. By convention:

Param Description
%1v is the error number itself, also the message number
%2v is the statement number in the IDL file
%3v is the starting character position of the error
%1d is the IDL filename
%2d is the last encountered token string

Messages in the 5001-5999 range are VB6 syntax errors. Message 5000 is the preamble message for these errors. By convention:

Param Description
%1v is the error number itself, also the message number
%2v is the statement number in the source file
%3v is the starting character position of the error
%1d is the Source filename
%2d is the last encountered token string
%3d is the source record beginning at the point the error was detected


 Opcodes Statement Summary

Opcodes is a nonterminal, metalanguage statement that initiates the definition of the operation codes in the intermediate language. A language specification may have only one Opcodes statement which must precede any of the statements that reference the operation codes. The actual numeric values of the operation codes and their associated subcodes are defined within gmBasic and must not the changed. The actual identifiers are used in the other statements in the language definition to refer to the operation codes, and could be changed assuming that all references to them are changed as well.

The Opcodes statement has no attributes.

The substatements of the Opcodes statement are as follows:

Substatement Description
Opcode This substatement defines an individual operation code in the intermediate language.


 Opcode Substatement Summary

Opcode is a nonterminal, metalanguage substatement that occurs within the Opcodes statement. This substatement defines an individual operation code in the intermediate language.

The attributes of the Opcode substatement are as follows:

Attribute Description
Id This attribute is the identifier of an operation code, It must be 3-characters and it must be unique.
Opc This attribute is the binary value, referred to as the "emission code", to be used when entering the operation into intermediate code storage. Each emission code must be unique and must be a value between 0 and 250. The operations should be numbered sequentially with as few holes in the numbering as possible.
Type This is an enumerated entry from the opcTypes enumeration which describes the type of the operation code.
Role This is an enumerated entry from the opcRoles enumeration which describes the general role the operation performs in the intermediate language.
Subcodes This integer value specifies the number of suboperations associated with the operation. A value of 0 indicates that the operation has no suboperations. The number of suboperations must be less the 256. If suboperations are specified, the opcode statement must be followed by that number of subcode statements.

The opcTypes enumeration has the following entries:

Entry Description
Arithmetic The arithmetic operators perform calculations, which may be actual arithmetic but might well be any other type of calculation like masking or concatenation or comparison. They typically have suboperations for the different binary types that may be involved.
SingleByte The single byte operators have simple generic roles within the intermediate language like introducing a new code sequence or marking the end of some sequence.
DoubleByte The double byte operators have generic roles within the intermediate language. Their emission consists of the operation emission code followed by the suboperation emission code. Within other statements they are referenced as OPC.Subcode.
ShortValue The short value operator emission is followed by a two-byte integer value used to specify a simple integer constant or number.
SymbolAddr The symbol address operators are followed by a four-byte integer value that specifies the root offset in the current storage area of a symbol defined within the source code.
StringAddr The string address operators are followed by a four-byte integer value the specifies the offset in current storage of a character string. This string might be an actual string or it might be a value constant of some sort.
VectorAddr The vector address operators are followed by a four-byte integer value that marks the offset of the start of a fixed size group of values. Since the VB6 language does not have a Data statement, as such, the gmIL contains no operators of this type.
BinaryType The binary type operators, not to be confused with Arithmetic binary operators, have a suboperation code that defines a binary type. They are used extensively in the intermediate code to specify the binary result-type of a sequence of operations.
LibraryAdr The library address operators are followed by a four-byte integer value that specifies the root in either current storage or language storage of an external symbol in use by the source code. Positive roots are to current storage; while negative roots are to language storage.
LibPattern The library pattern operators are followed by the offset of a surface pattern description either in the current storage area or in language storage.
ObjectType The object type operators have a suboperation code that specifies the type of object that the some sequence of operations pertain to.
StringCons The string constant operators are followed directly by a count-characters string. This operator complicates intermediate code traversal so there are none in gmIL.

The opcRoles enumeration adds details to the type specification above. It has the following entries:

Entry Description
NewLev There are many nested sequences of operators. This role starts a new nesting level.
EndLev There are many nested sequences of operators. This role ends a nesting level.
LoadSym This role loads a source code symbol.
LoadLib This role loads a library symbol.
LoadInt This role loads a short integer value.
LoadStr This role loads a character string.
LoadLng This role loads a string representation of a long integer constant.
LoadDbl This role loads a string representation of a real constant.
LoadLog This role loads a binary representation of a logical (boolean) constant.
LoadDat This role loads a string representation of a date constant.
LoadSpv This role loads a subcode that defines some source language particular special value like Me.
LoadTyp This role loads an enumeration entry value.
Unary This role defines a unary operator.
Binary This role defines a non-relational binary operator.
Relate This role defines a relational binary operator.
Member This role asserts the membership of a code sequence in the preceding code sequence.
Clsref This role asserts that the subcode refers to a class component
Convert This role performs a type-conversion of some sort.
Comment This role introduces a non-executable comment.

The substatements of the Opcode statement are as follows:

Substatement Description
Subcode This substatement specifies a suboperation of the operation code.

The attributes of the subcode statement are as follows:

Attribute Description
Id This attribute is the identifier of the suboperation. It must be unique within the parent operation. There is no restriction on the length of suboperation identifiers.
Value This is the suboperation emission value. It must be unique within the parent operation. It must between 0 and one minus the number of subcodes defined for the operation.


 Patterns Statement Summary

Patterns is a nonterminal metalanguage statement that initiates the definition of surface patterns for the operation codes in the intermediate language. A language specification may have multiple patterns statements that group the operation codes.

The Patterns statement has no attributes.

The substatements of the Patterns statement are as follows:

Substatement Description
Pattern This substatement defines the surface patterns for a given operation code in the intermediate language.


 Pattern Substatement Summary

Pattern is a nonterminal metalanguage substatement that occurs within the Patterns statement and within the Replace refactoring statement. This substatement defines the surface patterns for a given operation code in the intermediate language. When used within a Patterns statements the definition must be for a previously undefined surface pattern. When used within a Replace statement a previous surface pattern may be replaced.

The attributes of the Pattern statement are as follows:

Attribute Description
Id This attribute is the identifier of an operation code as defined in the Opcodes statement for the intermediate language.

The substatements of the Pattern statement are as follows:

Substatement Description
Subcode This nonterminal substatement specifies which suboperation of the operation code is to receive surface pattern definitions.
vbp This deprecated terminal substatement specifies a surface pattern for the Basic project file syntax.
vb7 This deprecated terminal substatement specifies a surface pattern for the VB6/ASP/VbScript source language syntaX.
csh This terminal substatement specifies a surface pattern for C# syntax.
vbn This terminal substatement specifies a surface pattern for VB.NET syntax.
gms This terminal substatement specifies a surface pattern for gmSL syntax.
jvs This terminal substatement specifies a surface pattern for JavaScript syntax.
usr This terminal substatement specifies a surface pattern for an external user specified syntax.
all This terminal substatement specifies an all other syntax. When used it must be the final statement in the set of surface patterns being defined. The author will use this pattern if no explicit pattern exists for the target language syntax currently being authored.

The attributes of the Subcode substatement are as follows:

Attribute Description
Id This attribute is the identifier of a suboperation code for the Pattern operation code as defined in the Opcodes statement for the intermediate language.

Any given operation code or operation code, subcode combination can have as many different surface patterns as needed associated with it. Operation codes that have no subcodes associated with them use this form.

   <pattern id="opc">
       <syntax 1 .../>
         ...
       <syntax n .../>
    </pattern>
Operation codes that have subcodes associated with them use this form.
   <pattern id="opc">
       <subcode id="subcode 1" >
          <syntax 1 .../>
            ...
          <syntax n .../>
       </subcode>
           ...
       <subcode id="subcode n" >
          <syntax 1 .../>
            ...
          <syntax n .../>
       </subcode>
    </pattern>
The script errors associated with the Pattern statement are as follows:

Error Description
1073 Encountered following when expecting 'pattern': %1d
1074 Pattern command missing required id attribute.
1075 The pattern identifier [%1d] is not recognized.
1076 The operation [%1d] already has surface forms specified.
1077 Encountered following when expecting 'subcode': %1d
1078 The required subcode identifier is missing.
1079 The component [%1d] is not defined for the operation"
1080 The subcode [%1d] already has surface forms specified.


 vbp,vb7,csh,vbn,gms,jvs,usr,or all Substatement Summary

The dialect syntax specific statements all have the same form. They specify the expected state of the string stack before and after a particular operation is encountered by the string machine. In addition they supply additional information about the role and status of the operation needed within the string machine and elsewhere. Overall these specifications are referred to as "surface forms".

The attributes of the surface form statements are as follows:

Attribute Description
Level An integer value specifying the precedence of the operator relative to others. As the output production proceeds, it is necessary to enclose certain operations in parentheses to achieve the proper order of evaluation. The current precedence of each operand is maintained. When two operators of lower precedence are combined via an operator of higher precedence, then they are enclosed in parentheses.
Status An optional keyword describing the overall status of the operation: Ok, Delete, Deprecated, NotImplemented, MustCorrect, NotIdent, Postfix, or NeedsPren.
Role An optional keyword describing the overall role of the operation: Unknown, Property, Method, Define, Utility, Command, Constant, Function, Event, Control, Collection, Resource, Index, or Migclass.
Narg An integer value specifying the number of operands associated with the operation -- i.e., whether the operation is null, or unary, or binary, etc. -- for the particular language. All operations are reverse polish; therefore, when a given operation is encountered, its operand strings have already been placed on the string-machine stack. The operands are numbered starting with the oldest first. In other words, the operand deepest on the stack is argument 1 and the operand at the top of the stack is argument n, for an n-ary operator.
Code A pattern string which specifies an arbitrary but fixed concatenation of the operands and of other character sequences which can be described via a linear pattern string. The pattern string describes not only how the operands are combined but also how the various constants, symbol table entries, and miscellaneous special-purpose conversion routines combine to form the final output.


 Content of pattern strings

Within the pattern strings there are three types of specifications. First, there are special operation parameters which consist of a backslash followed by a letter. These parameters trigger special conversions. Second, there are operand conversion parameters which consist of a percent sign, followed by a numeric digit, followed by a conversion code. The numeric digit specifies which operand is to be entered at this point in the string, and the conversion code specifies any special operation to be performed. Third, there are simple character specifications which are any characters not forming one of the two specifications above. Simple characters are entered into result strings exactly as entered.

The special operation parameter characters are as follows:

Char Description
c A statement has been completed. Write it to the current output text buffer and continue processing the pattern string. If the syntax of the dialect being authored requires an end of statement like ";" then add it. These end of statement characters should not be entered into the pattern strings directly.
e The operation code is followed by the storage offset of an enumeration entry in an external library or language file. Obtain the offset and enter its library-style identifier into the current statement.
ki The operation code is followed by a short integer value. Convert the value to string and enter it into the current statement.
kl The operation is followed by the offset of the string representation of a long or exact representation constant. Retrieve it, do any dialect specific editing that is needed, and enter it into the current statement.
kr The operation is followed by the offset of the string representation or a real constant. Retrieve it, do any dialect specific editing that is needed, and enter it into the current statement.
ks The operation is followed by the offset of a character string. Retrieve it and enter it into the current statement surrounded by quotes.
kp The operation is followed by the offset of a character string. Retrieve it and enter it as is into the current statement -- i.e. without quotes.
kc The operation is followed by the offset of a single-character string. Retrieve it and enter it into the current record surrounded by single or double quotes, depending upon the requirements for character constants in the target dialect.
l The operation is followed by the root offset of a component in an external library. Display the identifier of this component either as a fully qualified identifier (library.class.component) or as a simple identifier depending upon the context of its use in the intermediate code.
v The operation is followed by the root offset of a component in the user code. In cases where a qualified identifier is needed, simplify it depending upon the location of the reference.
V The operation is followed by the root offset of a user code component that is in a different project than the reference. The qualifications that have to be associated with the reference may have to be fully specified.
p The operation increases the logical nesting of the authored code. Write the current record and then increase the margin setting for the following records by the indentation margin width.
q The operation decreases the logical nesting of the authored code. Write the current record and then decrease the margin setting for the following records by the indentation margin width.
n Simply write the current record without associating any language specific end-of-statement characters.
f Flush the string stack -- enter all active entries on the string stack into the output record
m Enter without margin -- write the current record without a margin. The "m" pattern opcodes have a 0,1, or 2 to distinguish #if, #else, and #end; however that is not used in this implementation.
w Write the current record without a new line. This means that the following record written will be concatenated with this record in the final written record.
t Tab to an indicated position -- the "t" pattern code is optionally followed by an integer constant which indicates the absolute character position to which the current record should be tabbed. A value of 0 or no value, simply inserts a tab into the current record.
s Enter a single double quote character into the current record. These pattern codes are tracked by pair by the surface pattern author. If this is a second one entered, the characters after the first one are scanned for double quotes that need to be escaped and if found the language specific conventions are used.
S Enter a single or double quote into the output record depending upon the presence of <% in the current record. This is a special operator used for writing the ends of attribute values for HTML statements within ASP code. It switches between single and double quotes when the language level change.
R The operation is followed is by the offset of a stored resource. The label of that resource is entered into the current record.
B The operation is followed by the root offset of a control whose code needs to be written. First write the current record and then author the code associated with the control.
C The current record contains a comment that needs to be authored as such using the conventions of the target language and the various Select attributes that control the form and spacing of comments.
D The operation code is followed by the root offset of a component whose declaration needs to be authored. Do so and associate any inline comment that follows it with the declaration -- if possible.
E The operation ends the authoring of a control code started by the "B" pattern opcode. If it is followed by a 1 decrement the current indentation nesting level.
H This operation is a speciality operator for writing the arguments to be associated with a direct call to an event handler. The operation scans the code looking for the event handler being call and then determines from its description what the appropriate event arguments are in the target language.
Q This operation simply enters two double quotes -- typically indicating an empty string -- into the output record.
Qo One of the problems faced by the author involves authoring strings with embedded quotes in quoted form. The term for this is "Quote-enclosure". The Qcontext characters are used to control the process which uses special characters called "hard quotes" to distinguish quotes that have to be escaped from quotes that do not. The basic issue is that once the quotes in part of an output string have been escaped, they must not be escaped again. The terminal hard quote of a string then is a blocking quote. The "Qo" operation opens a string to be quoted by entering a blocking hard quote
Qq This Qcontext operation simple enters a hard quote at the possible end of a string.
Qr This Qcontext operation removes a terminating hard quote. It is needed for multiple concatenations where the termination expected by the proceeding pattern is now delayed to the end of the current pattern.
Qe This Qcontext operation ends a string to be quoted. This is where all the work is done. The entire current output record starting at the last blocking quote is searched for soft quotes which are then escaped. When the record is actually written, all hard quotes are displayed as quotes.
T The operation code is followed by the root offset of a component whose binary type display needs to be entered into the current record.
, This speciality operator, replace with comma, is used when possibly indexed assignments must be authored as calls to a Set operation. The current record is checked for an ending right-parenthesis and if present it is removed before a comma is entered into the record.
X This speciality operator, author asp Xml comment, checks the current record to see if it is an ASP include. If not it uses the target language appropriate annotations to make it a comment. If it is an include it then authors using the appropriate markup conventions.
b This operator enters a blank into the current record if it is needed to create a token break -- if the current ending character in the record is an identifier character.
\\ This operator simply enters a backslash into the current record.

Each conversion code has an argument string associated with it that was removed from the string stack. They all also compare the hierarchy levels as described above to determine if parentheses have to be entered. The conversion codes differ in what changes they make in the argument string before they enter it into the current record. The conversion code characters are as follows:

Char Description
d This code simply enters the argument with no editing.
i This code assumes that the argument is a class name whose corresponding interface name should be displayed instead.
U The standard way that transforms convert complex identifiers of the form id1.id2.id3 into simple identifiers is by changing the periods to underscores. This code here performs this operation on the argument string before it is entered.
o The argument string is the representation of an optional argument being passed to a subprogram. If it is empty and the current record ends in a comma then remove the comma.
q The argument from the stack is to be enclosed in quotes.
Q Here the string argument is to be entered into a context which will be subject the quote-enclosure. However any quotes within this string should not be escaped. This display type converts any soft quotes it finds in the argument into hard quotes. See the Qcontext discussion above.
u If the argument is enclosed in quotes, then remove them before entering it.
D The argument is to be decremented by one. It it is a valid numeric constant, compute its value, decrement it, and then redisplay it. If it is not a valid numeric constant append "-1" to it.
H This is a deprecated speciality operator which takes the argument as a hexadecimal constant which must be broken into a three part comma-delimited string.
P This is a speciality operator. The argument is an identifier with the possible form name1.name. Only the name1 part is desired.


 Statements Statement Summary

Statements is a nonterminal metalanguage statement that initiates the definition of the statements within an Xml-style language to be processed. The actual languages are the actual gmPL language and the Html language that embeds the ASP pages. Not all statements in the gmPL are defined in this way and the Html language statements are not fully parsed by the Asp compiler. However, the bulk of the statements in both languages are described via a Statements specification.

The attributes of the Statements statement are as follows:

Attribute Description
Id This attribute is the identifier of the set of statements being defined. In the case of gmBasic they are toollang and htmllang.

The substatements of the Statements statement are as follows:

Substatement Description
Statement This substatement defines the attributes of a statement within the xml-style language being defined.

The script errors associated with the Statements statement are as follows:

Error Description
1081 Statement command missing required id attribute.
1082 Unable to store STATEMENT vector: %1d
1083 Encountered following when expecting 'attribute': %1d


 Statement Substatement Summary

Statement is a nonterminal metalanguage substatement that occurs within the Statements statement. This substatement is used to specify which statements are available in the language and what the attributes are of those statements. Within the current implementation of the tool two such languages are defined -- the language of the tool itself in the file toollang.xml and the html language as it occurs within ASP in the file htmllang.xml.

The attributes of the Statement substatement are as follows:

Attribute Description
Id This attribute defines the keyword which triggers its processing. This attribute is required and must be unique within a given Statements specification.

The substatements of the Statement statement are as follows:

Substatement Description
Attribute This attribute defines one of the attributes associated with the statement.


 Attribute Substatement Summary

Attribute is a terminal metalanguage substatement that occurs within the Statement statement. This substatement specifies the information needed to store and retrieve attribute values from Xml-attribute value strings and binary information vectors. Semantically they are distinguished from Properties in that an attribute can be stored and accessed directly based on its location in a binary information vector, its type and its support info. Its initial input conversion does not require any individual runtime support. A property on the other hand is simply a shorthand notation for possibly two different methods -- get and set. Each of these methods requires individualized runtime support just as a method requires such support.

The attributes of the Attribute substatement are as follows:

Attribute Description
Id This attribute defines the keyword for one of the attributes of the statement. This attribute is required and must be unique within a given statement specification.
Type This attribute specifies the type of the actual value expression associated with the attribute. The actual processing of Xml statements proceeds in two steps -- first they are parsed and then their attribute values are optionally interpreted and stored in an information vector. The first step always occurs and ignores the type specification. In order for the second step to occur a type specification is required. The actual entries are described below.
Location Associated with each attribute is the word starting offset in the information structure of the start of its value. This location is normally computed by gmBasic. There are times when a given location in the structure is accessed via two different attributes, either for historical reasons or because there may be different ways in which the same attribute can be specified. When this happens the first attribute using the location should be defined in the normal way and then any following attributes should reference that attribute via a location attribute as in the following for the Select statement
                  <Attribute id="Name" type="string[64]" EditString="on" />
                  <Attribute id="ToolName" type="string[64]" location="Name" />
In this case the ToolName identifier is an alternate way of referring to the Select.Name property.
Editstring If this attribute is specified as on then upon input it is edited for global variable entries:

Entry Substitution
%% Enter a percent sign
%USR_VERSION% Platform specified user version identifier
%PRM_VERSION% Platform specified system version identifier
%PRM_BUILDID% Platform build signature string
%DATE% Current date using currently selected formatting options
%TIME% Current time using currently selected formatting options

Stringoff If this attribute is specified as on then the keyword off can be used during input to indicate that the attribute value is the empty-string.
Stringon If this attribute is specified as on then the keyword on can be use to indicate that though the actual attribute value is the empty-string the attribute should none-the-less be considered to have a value.
Projectfile If this attribute is specified as on then the value is assumed to identify a project or library file in the primary root of the symbol table. If it is a class name, then it becomes the class file or library file being named.
Opcode If this attribute is specified as On, then the value is assumed to identify one of the primary operation codes in the intermediate language.
Operation If this attribute is specified as On, then the value is assumed to identify an operation code (opcode.subcode) in the intermediate language.
Additive If this attribute is specified as On, then the value is masked into the location rather than being simply stored.

The actual entries in the Type attribute are as follows:

Entry Description
string The value of the attribute is an arbitrary character string that can have any content or length. It is isolated by the parser but is not processed by the interpreter.
string[n] The value of the attribute is an arbitrary character string that can have any content, but that can contain no more than (n-1) characters. The interpreter stores the string in null-terminated form in an information vector but truncates it to (n-1) characters if necessary.
integer The value of the attribute must contain an integer value. If interpreted, this value is calculated from the value string and stored in a word in the information vector. If the value string does not contain a valid integer, then an Xml error is triggered.
boolean The value of the attribute must contain an on/off value. If interpreted, the entry "on" is assigned a value of one, and the entry "off" is assigned a value of zero. A valid entry is stored in a word in the information vector. An invalid entry triggers an Xml error.
boolean[n] The value of an attribute must contain an on/off value. If interpreted, the entry "on" is assigned a value of one, and the entry "off" is assigned a value of zero. The constant n must have a value between 1 and 31. A valid entry is stored in the nth bit of a word in the information vector. An invalid entry triggers an Xml error.
enum-id This entry must be the identifier of an previously stored enumeration with integer entries within the language specification. If interpreted, the entry must match one of the entries for the enumeration. A valid entry stores the matching enumeration entry value in a word in the information vector. An invalid entry triggers an Xml error.

The script errors associated with the Attribute statement are as follows:

Error Description
1021 Attribute command missing required id attribute.
1022 Unable to store attribute vector: %1d
1023 Attribute command missing required type attribute.
1024 Location attribute [%1d] not defined.


 Types Statement Summary

Types is a nonterminal metalanguage statement that initiates the definition of the low level data types to be used by the parser. gmBasic has highly optimized retrieval algorithms that restrict the number of simultaneous retrieval sequences that can be occurring. The lowest level component of the compiler is the parser that converts the individual lexemes, the actual words and punctuation marks, in the source statements into token type, lexeme pairs. Tokens are language independent codes that identify the actual roles of lexemes. To do the parse gmBasic needs to do a retrieval that takes a lexeme and looks up its token type. A separate simple data type is needed to do this retrieval so that the low level parsing operation is guaranteed not to interfere with the higher level symbol table retrievals being performed by the compiler. This data type is referred to as a "standard list" which contains a simple collection of name, integer value pairs. The Types statement creates a set of standard lists that contain these lists of information needed by the parser. They are as follows:

List Description of use
Types The names and codes of the basic binary types recognized by the metalanguage. The names of the lists below are also considered to be "user types" within this list.
ReservedWords The Vb6 reserved words like And, As, ByRef, ByVal, DoEvents, etc. and their associated token type codes.
Symbols The VB6 symbols like +, _, ^, etc. and their associated token type codes.
JscriptWords The JavaScript reserved words and their associated token type codes.
JscriptSymbols The JavaScript symbols and their associated token type codes.
VbsWords The VbScript reserved words and their associated token type codes.
VbsSymbols The VbScript symbols and their associated token type codes

The Types statement has no attributes.

The substatements of the Types statement are as follows:

Substatement Description
Type This substatement defines either a simple entry in the Types list or introduces one of the secondary lists.


 Type Substatement Summary

Type is a terminal, or nonterminal metalanguage substatement that occurs within the Types statement. Both forms of the statement add an entry to the list of basic binary types recognized in the metalanguage. The nonterminal form adds a secondary list to the type.

The attributes of the Type statement are as follows:

Attribute Description
Id This attribute is the name of the name, value pair being entered into the Types list. These names must be unique within the list. They are not case sensitive.
Index This attribute is the value of the name, value pair being entered into the Types list. It must be an integer value between 0 and 255. It need not be unique.

If the statement is not terminal it introduces a secondary list that is accessible via the name. The substatements of the Type statement are as follows:

Substatement Description
Entry This substatement defines a simple entry in the secondary list.

The attributes of the Entry statement are as follows:

Attribute Description
Id This attribute is the name of the name, value pair being entered into the secondary list. These names must be unique within the list. They are not case sensitive.
Index This attribute is the value of the name, value pair being entered into the secondary list. It must be an integer value between 0 and 255. It need not be unique.

The script errors associated with the Type statement are as follows:

Error Description
1087 The list member identifier must be specified.
1088 Illegal statement in Types block: %1d


 Introduction to gmSL

The name gmSL stands for Great Migrations Scripting language. There are many places in the authoring and reporting facilities where detailed programming specifications can be supplied by the user. These specifications introduced by the gmSL statement use a subset of VB6 syntax.

In addition to specifying runnable procedures, the gmSL is also implemented within the processing of the gmPL statements. Once a complete gmPL statement record has been read, it is scanned for internal tag sequences <%=...%> or simply %...% sequences. These sequences are assumed to contain gmSL expressions. They are immediately compiled into intermediate code and executed via the runtime engine built into gmBasic. The result of the expression is then evaluated into string form and then substituted for the tag sequence. To emphasize, this substitution is performed on the raw gmPL statement records before they are seen by the actual statement parser.

gmSL is a language that gets information from the current gmBasic runtime and then writes that information into the current gmPL statement being processed, into the current output buffer being written by the author, or directly into a file created by the Output statement. gmSL does not have the facilities to change anything within the gmBasic runtime -- it is a retrieval and reporting capability.

As an example, the following set of gmSL commands in a script file

   <Select VirtualRoot="E:\gmSrc\Asp" />
   <Registry type="FixType" source="[E:\gmSrc\Asp\script\db_config.asp].SQLExecRS" target="ADODB.RecordSet" />
   <Compile PageSlice="E:\gmSrc\Chevin\script\main.asp" >
   </Compile>
can also be written as

   <select VirtualRoot="E:\gmSrc\Asp" />
   <Registry type="FixType" source="[(%= VirtualRoot %)\script\db_config.asp].SQLExecRS" target="ADODB.RecordSet" />
   <Compile PageSlice="%VirtualRoot%\script\main.asp" >
   </Compile>
As an example of supporting the author, the following authors the adornments needed to actually begin specifying the control properties for the form for both VB.NET and C#.
   Sub DesignSubProperties
      If LangIdent = "vbn" Then
         WriteLine "Me.SuspendLayout()"
      Else
         WriteLine "this.SuspendLayout();"
      End If
    End Sub
The compiled intermediate code version of this method is stored within the language file and is executed by the author as needed. It can also be overridden by the user. See the gmSL statement page.

As an example of writing directly into an output file, the following is the actual code used by the Symbols substatement of the Search statement.

   Sub SearchSymbols(ByVal Root As Symbol)
   Dim curNode As Symbol
      StartTable "Audit of Symbol tree in " & StorageName & " storage area"
      AddColumn("Lev",3)
      AddColumn("Address",8)
      AddColumn("Parent",8)
      AddColumn("Symbol Type",-30)
      AddColumn("Full Symbol Identifier",-100)
      WriteHeading
      For Each curNode in Root.Tree
         WriteText curNode.Level
         WriteCell
         WriteText curNode
         WriteCell
         WriteText curNode.Parent
         WriteCell
         curNode.DisplayObjectType
         WriteCell
         WriteText curNode.FullName
         WriteCell
         WriteRow
      Next curNode
      EndTable
   End Sub
Again, the compiled intermediate code version of this subprogram is stored in the language file and is executed by gmBasic when it executes the gmPL Search Symbols substatement.

As is clear from the above, many of the low level capabilities and information available to gmBasic are organized into classes that are made available to gmSL through the same types of class definitions in the language file that are used to define the external classes available to VB6. In addition there are many methods written in gmSL, like the two above that are stored in the language file and can be accessed via user authored gmSL code.

The page about the utility statement gmSL discusses how user authored gmSL can be introduced into command scripts. The discussion here describes the classes that are available as follows:

Class Description
Select The static Select class contains enumerations and properties that are directly specified by the user via the Select statement. The values of all current Select attribute values are available as properties in this class. These are described on the page for that statement.
Runtime The static Runtime class gives access to the current runtime information.
Author The static Author class writes information to the currently active output medium, which might be the text buffer being managed by the author or simply the current output file.
Symbol This dynamic class is the base class for all components stored in the symbol table. It provides properties and methods that apply to all stored components.
TextCode This is a static gmSL implemented class of utilities used extensively by the author.
AuditVbi This is a static gmSL implemented class of utilities use by the Search statement.


 The WYSIWYG Dilemma

Ask a potential user of a Great Migrations translation tool "What white space/line break conventions do want the tool to use in the translated code?" and he/she will answer "I don't know. Why don't you just use the same conventions as in the source?". The answer "When the tool authors the code, it does not know what the source conventions were." has been a show-stopper more than once. This issue is the WYSIWYG dilemma.

Pronounced WIZ-zee-wig. Short for what you see is what you get. A WYSIWYG application is one that enables you to see on the display screen exactly what will appear when the document is printed. This differs, for example, from word processors that are incapable of displaying different fonts and graphics on the display screen even though the formatting codes have been inserted into the file. WYSIWYG is especially popular for desktop publishing. Note that the WYSIWYGness of an application is relative. Originally, WYSIWYG referred to any word processor that could accurately show line breaks on the display screen. Later WYSIWYGs had to be able to show different font sizes, even if the screen display was limited to one typeface. Now, a word processor must be able to display graphics and many different typefaces to be considered WYSIWYG. Still, some WYSIWYG applications are more WYSIWYG than others. For example, many desktop publishing systems print text using outline fonts (PostScript fonts, for example). Many of these systems, however, use corresponding bit-mapped fonts to display documents on a monitor. What you see on the display screen, therefore, is not exactly what you see when you print out the document. In addition, standard laser printers have a resolution of at least 300 dpi, whereas even the best graphics monitors have resolutions of only 100 dpi. Graphics and text, therefore, always look sharper when printed than they do on the display screen. And colors often appear differently on a monitor than they do when printed out.

 The gmSL #TextStart and #TextRaw statements

A major role of gmSL is to write all of the various blocks of text required to produce .NET assembly files and their associated code files. These text blocks are often vary only by a few internal identifiers that are defined within the gmBasic runtime environment. The #TextStart and #TextRaw statements are used to simplify the authoring of these blocks of text.

The two statements differ in the way they interprete leading whitespace, which will be discussed below. Beyond that they are the same. Below is the start of the gmSL method that authors the start of a .NET project file. The parameter first contains "T" if this is the first project file being authored in the current run.

Sub Project_Preamble(ByVal first As String)
   IF first = "T" THEN
      #TextStart
      rmdir (%= DeployLocation %)
      mkdir (%= DeployLocation %)
      mkdir (%= DeployLocation %)\bin
      #TextEnd
   END IF
   #TextStart
   cat >(%= DeployLocation %)\(%= LocalName %).(%= LangExt %)proj <<'!)(!'
   #TextEnd
   If DevEnv = "VS2008" Then
      #TextStart
      <Project DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003" ToolsVersion="3.5">
         <PropertyGroup>
            <ProjectType>Local</ProjectType>
            <ProductVersion>9.0.30729</ProductVersion>
            <TargetFrameworkVersion>v3.5</TargetFrameworkVersion>
     #TextEnd

 Runtime class Summary

The static Runtime class gives access to the current runtime information that is not directly part of the Select class. This includes other system values, properties of the current project being processed, and various general methods.

 Runtime System values

The following Runtime properties give access to various system values that are not defined within the Select class.

 LangExt Property

Synopsis: string LangExt

There are some low level string enumerations hard-wired into gmBasic primarily for bootstrap purposes. This property returns the file extension for the currently selected target dialect. These are as follows:

Extension Dialect
"xml" LNG_SCRIPT
"vbp" LNG_VBPROJECT
"bas" LNG_BASIC
"vb" LNG_VBNET
"cs" LNG_CSHARP
"cs" LNG_USER
"gms" LNG_GMSL
"jav" LNG_JSCRIPT


 LangIdent Property

Synopsis: string LangIdent

There are some low level string enumerations hard-wired into gmBasic primarily for bootstrap purposes. This property returns the identifier for the currently selected target dialect. These are as follows:

Identifier Dialect
"xml" LNG_SCRIPT
"vbp" LNG_VBPROJECT
"vb7" LNG_BASIC
"vbn" LNG_VBNET
"csh" LNG_CSHARP
"usr" LNG_USER
"gms" LNG_GMSL
"jav" LNG_JSCRIPT


 ToolVersion Property

Synopsis: string ToolVersion

This is the version number of the release of gmBasic being run. If it is an intermediate release, then it will be a version number and a BETA number like V10.03(BETA.009). If it is a final release, then it will be a version number and a release date like V10.02(08/26/12).

 DeployLDF Property

Synopsis: boolean DeployLDF

This property is derived from the Select AuthorLibrary attribute value. If that value is set to Deploy, then this property is True; else it is False.

 SymbolRoot Property

Synopsis: gmsl.Symbol SymbolRoot

This constant property represents the root of the symbol table. It is used in For Each loops to start a traversal at the root of the symbol table. It should not be used in any other context.

 StorageName Property

Synopsis: string StorageName

This property is the Storage Identifier attribute value of the currently open storage area.

 Vb6 Project Information

The following Runtime properties pertain to the current VB6 project being authored.

 DeployLocation Property

Synopsis: string DeployLocation

If there is a DeployLocation Select attribute specified then this property simply has its value. If that attribute is not specified, then this property is computed using one of two templates from the metalanguage: GlobalDeploy or DeployLocation.

The GlobalDeploy template is used if the buildfile setting is Global. Its pattern strings are

   cshPattern="%1d\%2d_csh" vbnPattern="%1d\%2d_vbn"
Where the first string is the library location and the second string is the name attribute value from the project file.

The DeployLocation template is used if the buildfile setting anything else. Its pattern strings are

   cshPattern="%1d\%2d_%3d_csh" vbnPattern="%1d\%2d_%3d_vbn"
Where the first string is the parent directory of the directory that contained actual source vbp file, the second string is the name attribute value from the project file, and the third string is the Id Select attribute value.

 LocalName Property

Synopsis: string LocalName

This property is the local filename without its extension of the actual source vbp file for the current project.

 NameSpace Property

Synopsis: string NameSpace

This property is the value of the name attribute from the actual source vbp file for the current project.

 BuildType Property

Synopsis: string BuildType

This property is the value of the Type attribute from the actual source vbp file for the current project. It contains one of the following: Exe, OleDll, OleExe, or Control.

 Startup Property

Synopsis: string Startup

This property is derived from the value of the Startup attribute from the actual source vbp file for the current project. This attribute typically has entries like Sub Main, (None), or the name of the form to use to start execution. If the entry is Sub Main or an identifier then the identified component is sought in the symbol table. If found, its identifier in the target language, probably the same as the VB6 identifier unless it was refactored, becomes the value of this propery. If not the original vbp Startup value is used (without the Sub if there.

 AppObject Property

Synopsis: boolean AppObject

This property is True only if the current project code makes use of a "Application Wide Object" -- AppObject. This means that somewhere within the code of this project a reference is made to an external class or coclass that has an AppObject attribute specified, such as the following.
   <coclass id="HelpFile" appobject="kWHelpFile.HelpFileClass">
      <subclass id="_HelpFile"/>
   </coclass>
AppObjects are singleton classes, but it is up to the user code to implement the pattern, which means that only one instance of this class should be created and all references to components of this class must use that instance. The actual code added to the project is the standard Singleton pattern, C# version here, placed in the application code as opposed to being in the code for the class itself where it would normally be.
   public sealed class AppObject
   {
      private static kWHelpFile.HelpFile kWHelpFile_HelpFileInstance = null;
      public static kWHelpFile.HelpFile kWHelpFile_HelpFile
      {
          get
          {
            if(kWHelpFile_HelpFileInstance == null)
            {
               kWHelpFile_HelpFileInstance = new kWHelpFile.HelpFile();
            }
            return kWHelpFile_HelpFileInstance;
         }
      }
   }
and references to components look as follows.
   mnuK2Help.Text = AppObject.kWHelpFile_HelpFile.GetHelpMenuCaption();
The Runtime.AppObject property merely specifies that machinery of this sort is present and/or needed in the project code.

 SystemIO Property

Synopsis: boolean SystemIO

This deprecated boolean property was used to specify whether any code in the project was doing system level input/output, thus requiring special references. It is no longer set and is always False.

 DefInstance Property

Synopsis: boolean DefInstance

This property is True only if a Form defined within the project requires a DefInstance property. In VB6, form components can be referenced using the static class notation formName.componentName. In .NET, forms are dynamic classes which must be referenced using this or Me as opposed to formName within the code for the form and must be addressed via an instance of the form in code that is external to the form. The DefInstance property defined within the form provides this instance. Thus a VB6 code like
   Begin VB.Form Calculators
     ...
      Private Sub bttnLoan_Click()
         LoanCalc.Show
       End Sub
becomes this in the translated code (C# version)
      private void bttnLoan_Click(object sender, EventArgs e)
      {
         LoanCalc.DefInstance.Show();
      }
The actual implementation of the DefInstance property itself (C# version) has the following form
      Private Shared m_vb6FormDefInstance As (%= FormName %)
      Private Shared m_InitializingDefInstance As Boolean
      Public Shared Property DefInstance() As (%= FormName %)
         Get
            If m_vb6FormDefInstance Is Nothing OrElse m_vb6FormDefInstance.IsDisposed Then
               m_InitializingDefInstance = True
               m_vb6FormDefInstance = New (%= FormName %)()
               m_InitializingDefInstance = False
            End If
            DefInstance = m_vb6FormDefInstance
         End Get
         Set(ByVal value As (%= FormName %))
            m_vb6FormDefInstance = Value
         End Set
       End Property
The Runtime.DefInstance property merely specifies that machinery of this sort is present and/or needed in the code. It should be noted, that if any form within a project requires a DefInstance property, then that property is supplied for all forms.

 ToolTip Property

Synopsis: boolean ToolTip

This property is True only if a Form defined within the project has a control that has a tooltip. In VB6, tooltips are properties of individual controls. In .NET the form has a SetToolTip method which takes two arguments, the Control to associate the ToolTip text with, and the ToolTip text to display when the pointer is on the control. If tooltips are present, this declaration is added to each form (C# version)
   public System.Windows.Forms.ToolTip ToolTip1 = null;
and for controls that have a ToolTipText defined, such as
   Begin VB.CommandButton Command2
      Caption         =   "E&xit (with tooltip)"
      Height          =   495
      Left            =   3240
      TabIndex        =   1
      ToolTipText     =   "Exit program"
      Top             =   3360
      Width           =   1415
   End
the following is added to their designer code (C# version)
   this.ToolTip1.SetToolTip(this.Command2,"Exit program");
The Runtime.ToolTip property merely specifies that machinery of this sort is present and/or needed in the code.

 Resources Property

Synopsis: boolean Resources

This property is True only if the current Form File being processed had a set of resources associated with it that were originally stored in an frx file. In .NET, these resources are managed by the System.ComponentModel.ComponentResourceManager (C# version)
   System.ComponentModel.ComponentResourceManager resources =
           new System.ComponentModel.ComponentResourceManager(typeof(frmDownloader));
and are retreived via GetObject calls in the designer code such as (C# version)
   this.Image4.Image = (System.Drawing.Image)resources.GetObject("frmDownloader.frx2CDA.Picture");
The Runtime.Resources property merely specifies that machinery of this sort is present and/or needed in the code.

 ExeName Property

Synopsis: string ExeName

This property is the value of the Exename32 attribute from the actual source vbp file for the current project. It is the name of the library or executable that would have been produced by the original VB6 project.

 ProjectFile Property

Synopsis: string ProjectFile

This property is the full pathname of the actual source vbp file for the current project.

 ProjectName Property

Synopsis: string ProjectName

This property is the value of the Name attribute from the actual source vbp file for the current project.

 CurrentClass Property

Synopsis: gmsl.Symbol CurrentClass

This property is vbName component of the file whose content is presently being authored.

 IsInterfaceUser Property

Synopsis: boolean IsInterfaceUser

This property is True only if the current project has a registry command in the GlobalSettings file tied to its Exename32. This means that the project is using interfaces as controlled by this registry type.

 Runtime Methods

The methods in this class are general utility methods and some specialized authoring methods that are implemented within gmBasic itself.

 LocalFileName Method

Synopsis: string LocalFileName(string pathname)

This method views a the pathname as though it consisted of three concatenated components: directory + localname + extension. It returns the localname.

 FileName Method

Synopsis: string FileName(string pathname)

This method views a the pathname as though it consisted of three concatenated components: directory + localname + extension. It returns localname.extension.

 Directory Method

Synopsis: string Directory(string pathname [,integer remove])

This method views a the pathname as though it consisted of three concatenated components: directory + localname + extension. In addition it views the directory name as consisting of a series of subdirectories separated by slashes or backslashes. It returns the directoryname less remove subdirectories from the back. Any trailing slash or backslash is removed as well. remove is optional, and if omitted a value of zero is assumed.

 Guid Method

Synopsis: string Guid(string GuidName)

This method attempts to find the named Guid in the registry. It checks both the current storage area and the language storage area. If it cannot find it, it creates a GUID. As an example, consider the problem of assigning either a unique or fixed GUID to a name Project which is referenced elsewhere in a gmSL method.

   <Registry type="guid" source="Project" target="(%= Guid("new") %)" />

The Guid method attempts to find the GuidName in the registry. If it cannot find it, it creates a Guid. Since "new" does not exist, the above will assign a unique instance GUID to the Project GUID in the registry. If the same GUID is always wanted, simple change the above to something like

   <Registry type="GUID" source="Project" target="{11111111-2222-3333-4444-555555555555}" /

 Template Method

Synopsis: string Template(string TemplateName)

Templates are a group of properties stored in a Templates class in the language file. These properties have dialect specific surface pattern strings associated with them. The methods retrieves the pattern string for the current target dialect for the property whose name is specified in the TemplateName argument.

 InitializeCode Method

Synopsis: void InitializeCode()

The constructor for forms has the following fixed form

   public partial class %FormClass% : MigrationSupport.UI.Form
   {
      private bool _disposed = false;
      public %FormClass%()
      {
         //
         // Required for Windows Form Designer support
         //
         InitializeComponent();

         //
         // TODO: Add any constructor code after InitializeComponent call
         //
         if (DesignMode) return;
             ....
      }
This method scans the components within the current form to determine if any added constructor code is needed and, if so, authors it. The primary code needed is the initialization of control arrays, such as
         cmdNumber = new System.Collections.Generic.SortedList<int, System.Windows.Forms.Button>();
         cmdNumber.Add(0, _cmdNumber_0);
            ...
and any needed "Form_Resize(null, null)" calls.

 Interface Method

Synopsis: void Interface()

VB6 classes can be used as interfaces by other classes via an Implements statement in that other class. If a class is implemented then in addition to authoring its actual implementation, gmBasic must also author an interface. This method checks to see if the current class needs to define an interface, and if so, authors it.

 SharedFileUsing Method

Synopsis: void SharedFileUsing()

This specialized authoring method checks to see if the current project uses any external shared files. These are files that were part of the current project code set, but are no longer because they were also part of another project. It is that other project that now defines them. To make the references to these now external components well-formed Using statements need to be added to the current code. If needed, this method authors these statements.

 DefineConstants Method

Synopsis: void DefineConstants()

When the Select ComputeConditional attribute is Migrate, gmBasic attempts to do a full migration to the .NET languages. In this context, this method checks for any referenced conditional constants define in the current project file via a condcomp attribute and adds their declaractions to the project file being authored within a

  <DefineConstants>...</DefineConstants>
specification.

 ConstDeclare Method

Synopsis: void ConstDeclare()

When the Select ComputeConditional attribute is Migrate, gmBasic attempts to do a full migration to the .NET languages. In this context, this method checks for any referenced conditional constants define in the current project file via a #const directives their declaractions to to the current code file being authored.


 InterfaceClasses Method

Synopsis: void InterfaceClasses(string Location)

When gmBasic is processing circular references by using interfaces, it must at some point create a .NET assemply that contains these interfaces. This method authors the Compile Include directives to add the actual target interface code files into that assembly. The argument Location is the directory location of those code files. The method does a directory search of this location for code files to produce the actual list of files to be included.

 Symbol class Summary

The Symbol class is the root class for all symbols stored in a virtual binary information file.

 Ident Property

Synopsis:
<Property id="Ident" type="String" status="ByVal" opcode="SYM.Ident" />

 Name Property

Synopsis:
<Property id="Name" type="String" status="ByVal" opcode="SYM.Name" />

 ObjectType Property

Synopsis:
<Property id="ObjectType" type="gmsl.ObjectType" status="ByVal" opcode="SYM.ObjectType" />

 Parent Property

Synopsis:
<Property id="Parent" type="Symbol" status="ByVal" opcode="SYM.Parent" />

 Tree Property

Synopsis:
<Property id="Tree" type="Collection" status="ByVal" opcode="SYM.Tree" />

 Children Property

Synopsis:
<Property id="Children" type="Collection" status="ByVal" opcode="SYM.Children" />

 Level Property

Synopsis:
<Property id="Level" type="Integer" status="ByVal" opcode="SYM.Level" />

 FullName Property

Synopsis:
<Property id="FullName" type="String" status="ByVal" opcode="SYM.FullName" />

 DisplayObjectType Method

Synopsis:
<Method id="DisplayObjectType" type="void" nPram="0" opcode="SYM.DispObjectType"/>

 WriteNamedFlags Method

Synopsis:
<Method id="WriteNamedFlags" type="void" nPram="1" opcode="SYM.WriteNamedFlags" >
    <Argument id="flags" type="Integer" status="ByVal"/>
</Method>

 WriteSurfacePattern

Synopsis:
<Method id="WriteSurfacePattern" type="void" nPram="1" opcode="SYM.WriteSurfacePattern" >
    <Argument id="pattern" type="Integer" status="ByVal"/>
</Method>

 MigInfo class Summary

The MigInfo class encompasses all symbols that can be migrated in a virtual binary information file. Its parent is the Symbol class.

 migPattern Property

Synopsis:
 <Attribute id="migPattern" type="Integer" />

 migFlags Property

Synopsis:
<Attribute id="migFlags" type="MigProcessFlags[]" />

 migStatus Property

Synopsis:
<Attribute id="migStatus" type="MigStatusFlags[]" />

 migComment Property

Synopsis:
<Attribute id="migComment" type="String" />

 migTransform Property

Synopsis:
<Attribute id="migTransform" type="Integer" />

 migRuntime Property

Synopsis:
<Attribute id="migRuntime" type="Integer" />

 context Property

Synopsis:
<Attribute id="context" type="contextFlags[]" />

 aspContext Property

Synopsis:
<Attribute id="aspContext" type="AspContextFlags[]" location="context" />

 Author class Summary

The static Author class is used to write information to the currently active output medium. Though this may be a physical text file, in most cases it is a record storage stream contained within the currently active user storage area. Though this class is able to physically manage files and make them the currently active output medium, in most cases the user of this class need not be concerned with the physical disposition of the information being authored. To simplify the documentation of the components of this class the term "written" will be used when in fact the actual operation performed is a storage in an information stream.

 WriteLine: Write a Line of Text

Synopsis:
<Method id="WriteLine" type="void" opcode="WRT.WriteLine">
   <Argument id="text" type="string" status="ByVal"/>
</Method>
This method appends the content of its argument to the current output record and then physically writes the content of that record to the currently active output medium. It then zeros the current number of characters in the current record; thus, emptying it. Its parameter is as follows:

Parameter Description
string Contains the string to be appended to the current output record before it is written.

There is no return value.

 WriteText: Write Text to Record

Synopsis:
<Method id="WriteText" type="void" opcode="WRT.WriteText">
   <Argument id="text" type="string" status="ByVal"/>
</Method>
This method appends the content of its argument to the current output record. No formatting is applied to the string. No actual write occurs at this time. Its parameter is as follows:

Parameter Description
string Contains the string to be appended to the current output record.

There is no return value.

 OpenOutput: Open Secondary Output File

Synopsis:
<Method id="OpenOutput" type="void" opcode="WRT.OpenOutput">
   <Argument id="FileName" type="string" status="ByVal"/>
</Method>
This method creates a text file and makes it the currently active output medium. Until the CloseOutput is called all further activity by this class will be directed to this secondary file. The content of the output medium that was active when this method is called is uneffected. Alternatively it is very important the close this secondary file before returning control to the tool, since without closure any records that the tool authors would also go to this file. At the present time only one secondary output file is supported by this class. The maximum output record size for the file is set 8192 and the current margin indentation width is set equal to the value being used by the primary output medium. Its parameter is as follows:

Parameter Description
FileName Contains the full pathname of the file to be created to receive output. If a text file with the specified name cannot be created for some reason, then Standard Output will receive the following output.

There is no return value.

 CloseOutput: Close Secondary Output File

Synopsis:
 <Method id="CloseOutput" type="void" opcode="WRT.CloseOutput"/>
This method closes the currently open secondary output file and restores the primary output medium as the currently active one. When OpenOutput has been used, it is very important the close this secondary file before returning control to the tool, since without closure any records that the tool authors would also go to this file.

There are no parameters.

There is no return value.

 SetIndentation: Set Margin Indentation

Synopsis:
<Method id="SetIndentation" type="void" opcode="WRT.SetIndentation">
   <Argument id="width" type="integer" status="ByVal"/>
</Method>

This method is used to set the indentation width for the current output medium for each margin level. Its parameter is as follows:

Parameter Description
width It is ofter desirable to indent records when writing output reports or computed code. This integer specifies the number of spaces to indent per indentation level set for the margin. A value of zero specifies that a tab should be used for each level. The default for this property is 3.

There is no return value.

 IncreaseMargin: Increase Margin Level

Synopsis:
<Method id="IncreaseMargin" type="void" opcode="WRT.IncreaseMargin"/>
This method increases the margin level being used for the current output medium by one. The resulting width of the displayed margin will be the level of the margin times the indentation width or the level number of tabs.

There are no parameters.

There is no return value.

 DecreaseMargin: Decrease Margin Level

Synopsis:
<Method id="DecreaseMargin" type="void" opcode="WRT.DecreaseMargin"/>
This method decreases the margin level being used for the current output medium by one. If the current margin level is at zero, then this method does nothing. The resulting width of the displayed margin will be the level of the margin times the indentation width or the level number of tabs.

There are no parameters.

There is no return value.

 NewLine: Write New Line

Synopsis:
<Method id="NewLine"        type="void" opcode="WRT.NewLine"/>
This method physically writes the content of the output record to the currently active output medium. It then zeros the current number of characters in the current record; thus, emptying it.

There are no parameters.

There is no return value.

 LogError: Log Error Message

Synopsis:
<Method id="LogError" type="void" opcode="WRT.LogError">
   <Argument id="Number"  type="integer" status="ByVal"/>
   <Argument id="Message" type="string"  status="ByVal"/>
</Method>
This method sets the system error code to a specified number and then writes a message to the current log file with the following format.
RUNERR#(%= Number %): (%= Message %)
Its parameters are as follows:

Parameter Description
Number This integer specifies the value to be assigned to the system error code and to be displayed as part of the error message. Its value is up to the user.
Message This string forms the bulk of the actual message displayed in the log file.

There is no return value.

 OutStyle: Style of Output to be Used

Synopsis:
<Property id="OutputStyle" type="OutStyle" opcode="WRT.OutputStyle" />

<Enumeration id="OutStyle">
   <entry id="Text"    value="0" />
   <entry id="Html"    value="1" />
   <entry id="Tabbed"  value="2" />
</Enumeration>
Besides authoring record-oriented translations, the Author can also be used to write tabular reports based on the information collected while the tool was processing the source codes. This property specifies the output style to be used when producing these tabular reports. They can can be produced in one of three styles: simple tab delimited, text tabular, or html tabular.

 NoMargin: Write New Line with No Margin

Synopsis:
<Method id="NoMargin"      type="void"     opcode="WRT.NoMargin"/>
This method physically writes the content of the output record to the currently active output medium using no margin. It then zeros the current number of characters in the current record; thus, emptying it.

There are no parameters.

There is no return value.

 StartTable: Start New Table

Synopsis:

There is no return value.

 AddColumn: Set Margin Indentation

Synopsis:

There is no return value.

 WriteHeading: Set Margin Indentation

Synopsis:

There is no return value.

 WriteCell: Set Margin Indentation

Synopsis:

There is no return value.

 EndTable: Set Margin Indentation

Synopsis:

There is no return value.

 WriteRow: Set Margin Indentation

Synopsis:

There is no return value.

 CloseWriter: Set Margin Indentation

Synopsis:

There is no return value.

 CreateWriter: Set Margin Indentation

Synopsis:

There is no return value.

 AppendWriter: Set Margin Indentation

Synopsis:

There is no return value.

 Initialize: Set Margin Indentation

Synopsis:

There is no return value.

 Runtime class Summary

The static TextCode class contains the methods used by the Author to write the various file subsections and annotations needed to publish .NET assemblies and code. All methods are void.

 Project_Preamble Method: Author Project File Preamble

This method is the initial method called when the tool begins authoring a a project file, and the assembly file, for either C# or VB.NET. It begins with the instructions needed by the deployment tool and authors everything needed up to the point where the "Reference Include" statements begin.

The method has no parameters.

 Project_StartCompile Method: Author Project File Compiles

Once the references section of the project file as been authored the actual compilations to be performed must be specified. This begins by closing the References item group and then listing the default Imports ItemGroup and then the start of the compile ItemGroup whose first member is always the Assembly file.

The method has no parameters.

 Project_Assembly Method: Author Project Assembly Compile

This method authors the Compile directive for the project assembly.

The method has no parameters.

 Project_EndCompile Method: Author End of Project File Compiles

Once the compilation ItemGroup has been authored this method is used to author the remaining text needed in the project file for both C# and VB.NET. The last line written by the method is the actual "!)(!" deployment meta symbol used to mark the physical end of a file within the deployment bundle.

The method has no parameters.

 Summary AssemblyFile Method: Author Assembly File

This method authors the entire Assembly File needed for either a C# or VB.NET build in the form needed for inclusion in a deployment bundle. As authored here the file contains all the comments and boilerplate normally seen in these files. These could probably be removed, if desired.

The method has no parameters.

 DesignFileBegin Method: Author Design File Beginning

Author the beginning of the Design file partial class. This has the following logical components:
  1. The cat statement for the Design partial class.
  2. The namespace (note the wizard has no namespace)
  3. The declaration for the start of the Designer Code Region. There is much variablity in where this declarion occurs and in how it is indented.
  4. If needed, the logic needed to implement the DefInstance property for the form.
Both the C# and VB.NET versions are authored by this method The parameters of this method are as follows:

Parameter Description
FormName The class name of the Form


 DesignSubInitialize Method: Author Designer Initialize

Authors the InitializeComponents method which is required by the Windows Form designer for both C# and VB.NET. If needed, the initialization of the resources and ToolTip1 components is included. The parameters of this method are as follows:

Parameter Description
FormName The class name of the Form


 DesignSubProperties Method: Author Designer Suspend

Authors the adornments needed to actually begin specifying the control properties for the form for both VB.NET and C#. At this time this is a simple SuspendLayout call.

The method has no parameters.

 DesignFileEnd Method: Author Design File End

All of the control and form property specifications have now been authored. This method authors the end of the designer file for both VB.NET and C# followed by the deployment meta symbol "!)(!" which marks the end of a file in the deployment bundle. Note that once the specifications themselves have been made both the methods ResumeLayout and PerformLayout are called.

The method has no parameters.

 ControlCodeBegin Method: Author Actual Control Code

Once the designer file has been written, this method begins the authoring of the actual control class for both VB.NET and C#. This includes:
  1. The cat statement needed by the deployment tool
  2. Any imports or usings that may be needed
  3. The namespace and class declarations
  4. The default constructor which deals with intializing the DefInstance if needed and then initializing any other components as needed.
The parameters of this method are as follows:

Parameter Description
FormName The class name of the Form
parentClass The .NET class that this class inherits from.
hasTerminate True if form has Class_Terminate


 ControlCodeMain Method: Author Control Main Method

Authors the code for the main method of a C# application. This is not needed for VB.NET. As authored here, the main method simply does an Application.Run on the form name. The parameters of this method are as follows:

Parameter Description
FormName The class name of the Form


 ControlCodeEnd Method: Author Control Code End

Simply authors the end of the control code class and namespace for both VB.NET and C# followed by the deployment meta symbol "!)(!" which marks the end of a file in the deployment bundle.

The method has no parameters.

 ResxInfo Method: Author ResX Information File

Authors the beginning of a Resx Information as is used to store the values of resources within controls. Note that it contains a long description comment that is usually seen with all resx files. If this is not desired it can be turned off by selecting the attribute Migrate2="on". Note that empty resource files are often created even when no resource data is present. At this point the tool authors a resx file only if resource data is present. The parameters of this method are as follows:

Parameter Description
FormName The class name of the Form


 ResxEnd Method: Author Resx File End

Simply authors the end of the resx information file folllowed by the deployment meta symbol "!)(!" which marks the end of a file in the deployment bundle.

The method has no parameters.

 ModuleFile Method: Author Module File Start

This method is the initial method called when the tool begins authoring a module file for either C# or VB.NET. It begins with the instructions needed by the deployment tool and then authors everything needed up to the point where the actual user code translation begins. The parameters of this method are as follows:

Parameter Description
ModuleName The class name associated with the module


 EndModule Module: Author End of Module File

Once the translation of the actual user code in a module file has been authored, this method is used to author the remaining text needed in the module file specification for both C# and VB.NET. The last line written by the method is the actual "!)(!" deployment meta symbol used to mark the physical end of a file within the deployment bundle.

The method has no parameters.

 ClassFile Method: Author Class File Start

This method is the initial method called when the tool begins authoring a a class file for either C# or VB.NET. It begins with the instructions needed by the deployment tool and writes everything needed up to the point where the actual user code translation begins. The parameters of this method are as follows:

Parameter Description
ClassName The name associated with the class in the source code
IntClassName If the class has not been implemented then this is the same as the class name; else it is the class name as modified by the "IntClassName" template.
ParentName A character string that contains the list of the parents of the class. In this the "class parents" are the class that this class inherits along with any interfaces that it implements. There are two posible output formats. One used in C# is a simple comma delimited list which is then associated with the definition of the class. For VBN there are two statements that are used -- "Inherits" and "Implements". These are inserted at the appropriate places in the list and if both are needed it contains the VBN multi-statement colon between them.
ServiceName If the class requires "System.Runtime.InteropServices" then this string contains the service name. At the present time it is nonempty only when used with the comsvcs library in transaction mode.


 EndClass Method: Author End of Class File

Once the translation of the actual user code in a class file has been authored, this method is used to author the remaining text needed in the class file specification for both C# and VB.NET. The last line written by the method is the actual "!)(!" deployment meta symbol used to mark the physical end of a file within the deployment bundle.

The method has no parameters.

 EventHandler Method: Author an Event Handler

This method is the initial method called when the tool begins authoring an event. This method does nothing for VB.NET; only C# requires any additional components to implement events. The parameters of this method are as follows:

Parameter Description
EventName The name associated with the event in the source code
CallArgs A string that contains the full declaration of the calling arguments for the delegate and the OnEvent_Event declaration.
ArgNames A string that contains argument names only as needed in actual call to the event.


 LocalNewc1 Method: Begin Local External Wrapper Code

This method is the initial method called when the tool begins authoring a local wrapper for an imported library. It simply authors the "cat" statement needed by the deployment tool. An authored wrapper of this type is referred to as a "Native External Wrapper Code", or simply "Newc". The parameters of this method are as follows:

Parameter Description
ExternalName The name associated with the imported library.


 WriteBuildFile Method: Write Build Project File Command

When the "BuildFile" select attribute has been turned "on", the tool calls this method to add an "EXECUTE msbuild" command for the authored project file as a final statement in the deployment file.

The method has no parameters.

 WriteSharedReference Method: Author a Shared Reference

When external libraries are referenced to satisfy shared references, this method authors the entry in the project file. The parameters of this method are as follows:

Parameter Description
lName Name of library containing shared component.


 WriteGlobalReference Method: Write reference to Global External

This method writes references to external global dependencies that are under the control of the ProjectReference Select attribute. The implementation of this property is complicated by the fact that the originally authored project file and the downstream reference to that project file must have matching GUIDS specified. The parameters of this method are as follows:

Parameter Description
lName Name of global external reference
projGuid Guid to be associated with the reference.


 DeclareLibrary Method: Declare Newc Library

This method begins the authoring of library declarations within the native external wrapper code for both C# and VB.NET. It begins by authoring the Imports or using statements needed abd then writes the namespace statement. The parameters of this method are as follows:

Parameter Description
ExternalName The name associated with the imported library.
hasForEach If the library will declare any enumerators then this string should be set equal to "T", else it should be set to "F".
colObject If the library will make reference to a collection then this string should be set equal to "T", else it should be "F".


 LocalNewc2 Method: End Local External Wrapper Code

This method is the final method called when the tool finishes authoring a local wrapper for an imported library. It simply authors the end of the namespace followed by the actual "!)(!" deployment meta symbol used to mark the physical end of a file within the deployment bundle.

The method has no parameters.

 AppObject1 Method: Author Start of AppObject Class

When a project being authors references external components that have AppObjects a class is needed to define the refence/creation properties for those methods. This method authors the start of that class.

The method has no parameters.

 AppObject2 Method: Author AppObject Property

When a project being authors references external components that have AppObjects a class is needed to define the refence/creation properties for those methods. This method authors one of these properties. The parameters of this method are as follows:

Parameter Description
appName The name of the library that contains the AppObject class
appClass The name of the class requiring an AppObject.


 AppObject3 Method: Author End of AppObject Class

When a project being authors references external components that have AppObjects a class is needed to define the refence/creation properties for those methods. This method authors the end of that class.

The method has no parameters.

 LibStart Method: Author Start of Local Library Description

When the AuthorLibrary Select specifies that a local description file is to be authored for a translated project, this method authors the start of that file.

The method has no parameters.

 LibEnd Method: Author End of Local Library Description

When the AuthorLibrary Select specifies that a local description file is to be authored for a translated project, this method authors the end of that file.

The method has no parameters.

 ReferenceMigSupport Method: Author Migration Support Reference

When a translation requires the use of a migration support library, this method writes the reference for in in the project file. The parameters of this method are as follows:

Parameter Description
isLocal If the migration support library is local to the target code project, then this string should be set equal to "T", else it should be "F".


 ImportsFileName Method: Author Imports File Name

This method authors the name of the ImportList file. This file introduces a command script that contains a series of reference subsidiary. Rather than authoring any local stubs with the translated codes gmBasic can instead manage imports list of all referenced components. in all imported references. Once completed, this statement authors the stub code for them.

The method has no parameters.

 ExternalLocation Method: Author an External Location

This method authors a file path location for an external component either in the library location, if defined; else in the local location. The parameters of this method are as follows:

Parameter Description
ExternalName The name of the external component


 ImportHintpath Method: Author a Hintpath for an External

This method authors the default hintpath in a bin subdirectory for an imported external component. The parameters of this method are as follows:

Parameter Description
ExternalName The name of the external component


 StartNewcProject Method: Start External Wrapper Code Project

This method authors the start of the project file needed for the external wrapper code stubs for an external library. The parameters of this method are as follows:

Parameter Description
ExternalName The name of the external library


 EndNewcProject Method: End External Wrapper Code Project

This method authors the end of the project file needed for the external wrapper code stubs for an external library. The parameters of this method are as follows:

Parameter Description
ExternalName The name of the external library


 ExternalBuildFile Method: Author Build Request

This method authors the deployment request to actually build a deployed .NET code project. The parameters of this method are as follows:

Parameter Description
ExternalName The name of the code project


 StartWebProject Method: Author Start of Web Project File

This method authors the start of the project file for a set of migrated ASP pages. The parameters of this method are as follows:

Parameter Description
ProjectName This is the overall name of the web code project
WarnErr This is the string to be used for the TreatWarningsAsErrors attribute in the project file.
GuidProject This is the GUID string to be used for the ProjectGuid attribute in the project file.
GuidType1 This is the first GUID string to be used for the ProjectTypeGuids attribute in the project file.
GuidType2 This is the second GUID string to be used for the ProjectTypeGuids attribute in the project file.


 WebFixedReferences Method: Author Fixed References for Web Project

This method authors the references in a Web project file that are used for all web projects.

The method has no parameters.

 EndWebProject Method: Author End of Web Project File

This method authors the end of the project file for a set of migrated ASP pages. The parameters of this method are as follows:

Parameter Description
ProjectName This is the overall name of the web code project
GuidFlavor This is the GUID string to be used for the GUID attribute of the FlavorProperties statement in the project file.
AspParse If this is "Yes" then instructions are added to the project file for the AspNetCompiler to do an AfterBuild.


 asp_endpage Method: Author End of ASP page

This method writes the termination mark for an ASP page in its deployment file.

The method has no parameters.

 register_codebehind Method: Author Codebehind Register Command

This method authors the Register ASP metacommand for a codebehind class and an include file.

Parameter Description -------------- ----------- PageClassName The class name for the codebehind. IncludeName The identifier of the include file

 declare_crosslink Method: Author CrossLink Declaration

This method declares a crosslink when needed in an ASP pageslice migration to codebehind. The parameters of this method are as follows:

Parameter Description
NameSpace The namespace containing the crosslink
ClassName The class of the crosslink


 asp_vbnetlib Method: Author VBNET Import for ASP

This method authors the VBNET=Microsoft.VisualBasic for an ASP code page.

The method has no parameters.

 asp_HostPage Method: Author ASP HostPage declaration

This method authors the host page declaration for a page class. The parameters of this method are as follows:

Parameter Description
PageClassName The name of the hosting page class -- the class type of the host page


 asp_NewInclude Method: Author Include Page Constructor

This method authors the constructor for an Includefile based class that has a parent host page. The parameters of this method are as follows:

Parameter Description
PageClassName The name of the parent page class
ClassName The name of the include class


 TypeInferenceFile Method: Author Name of TypeInference File

This method constructs the name of the TypeInference file based on a system identifier. The parameters of this method are as follows:

Parameter Description
SystemId This contains the system identifier to be added to the name of the file


 PrinterReference Method: Author Printer Reference

This method authors the reference in a project file for Printer references in the code. The default assumes that the Microsoft PowerPacks are being used.

The method has no parameters.

 AddUserCompiles Method: Add compiles

Place holder to be overridden by user with their code to add source files to the compile nodes in the .NET project file.

The method has no parameters.

 AddUserReferences Method: Add References

Place holder to be overridden by user with their code to add assemblies to the reference nodes in the .NET project file.

The method has no parameters.

 Audit class Summary

The static AuditVbi class contains the methods used by the Search statement to write the various audit reports.

 SearchSymbols Method: Search for All Symbols

This method performs a symbol search of symbols below a specified root symbol and writes an audit report which includes the Level of the symbol in the symbol table, the root address of the symbol, the root address of the parent of the symbol, the storage object type of the symbol, and the fully qualified identifier of the symbol.

Parameter Description --------- ----------- root The root symbol whose children are to be audited.

 WriteMigInfo Method: Audit MigInfo of symbols

All symbols in the symbol table that can be migrated inherit from the gmSL.MigInfo class. This method writes an audit report on the values of the properties in this parent class which include Migrate Status, Migrate Flags, Migrate Comment, Migrate Pattern, Transformation, and Runtime Flags.

Parameter Description --------- ----------- curNode A symbol that inherits frm the gmSL.MigInfo class.

 gmniIntroduction

Though most of the operations needed by the translation tools as executed via their internal runtime code are sufficient to suport migration projects, it is sometimes necessary to code at the C level. The facilities used to do this are called the "gmNI" pronounced "GeMiNI" and meaning the "Great Migrations Native Interface". The term "Native Interface" is borrowed from Java. As described by Wikipedia as "The Java Native Interface (JNI) is a programming framework that enables Java code running in a Java Virtual Machine (JVM) to call and to be called by native applications (programs specific to a hardware and operating system platform) and libraries written in otherlanguages such as C, C++ and assembly". The Great Migrations Native interface (gmNI) is a programming framework that enables Great Migrations translation tools to call and be called by native dynamic-link-libraries written in C.

The gmNI enables one to write native methods to handle situations when an migration cannot be written entirely in gmSL (Great Migrations Scripting Language), e.g. when the standard capabilies of the translation tool do not support some operation needed by the compiler, analyser, author, or auditor.

Code to be made available to a translation tool is linked ito a dynamic-link-library that is executed by the tool when certain events occur. As part of that execution the library is passed a set of handles to the methods available within the translation tool.

 The gmNI Code Events

The gmNI enables one to write native methods to handle situations when an migration cannot be written entirely in gmSL (Great Migrations Scripting Language), e.g. when the standard capabilies of the translation tool do not support some operation needed by the compiler, analyser, author, or auditor.

Code to be made available to a translation tool is linked ito a dynamic-link-library that is executed by the tool when certain events occur. As part of that execution the library is passed a set of handles to the methods available within the translation tool.

 Command Event Summary

gmniUtility statements are statements made accessable to command scripts via a gmNI event. Whenever the command script processor encounters a statement in a script that it does not recognize it triggers triggers the ExecuteCommand event. handler in each loaded runtime DLL that has this handler defined in the order that the DLLs were loaded. If one of these handlers returns a non-zero value, then the tool assumes that the XML command was processed by that DLL and ends its search. If no DLL indicates that it has processed the command, then the tool issues a command not found error. For this example let the command "FindDimAsNew" be used to scan a set of existing VBI files for class files that do not define a collection but do define a Class_Initialize() method and for Form files that define a Form_Load method. Since third-party libraries are not translated the first rule is easily met. Since being "private" does not effect the presence of methods in the VBI file the third rule is also met. The initial bit of code needed then is as follows:
  •  void ExecuteCommand_FindDimAsNew(char* command,int nCommand);
    
     DLL_EXPORT int ExecuteCommand(char* command,int nCommand)
     {
        auto int iRet;
    
        selectFlags = (tVb7Flags*)(Select_GetFlags());
        if(String_Compare(command,"<FindDimAsNew",13) == 0)
        {
           iRet = 1;
           ExecuteCommand_FindDimAsNew(command,nCommand);
        }
        else iRet = 0;
        return iRet;
     }
    
This code can be added to any Runtime DLL currently being loaded or could be placed in the main control logic of a separate DLL. If there is already an ExecuteCommand() handler present the above logic could be added with an else if. Again, the actual acceptance and execution of the command is triggered entirely by its initial command word. The actual implementation of the command in ExecuteCommand_FindDimAsNew() will be presented below. A translation script that might use this command is as follows:
  •  <gmBasic>
        <Storage Action="Create" Identifier="DimAsNewEntries" />
        <LoadRuntime Dllname="DimAsNew.dll" />
        <Output Status="New" Filename="DimAsNewEntries.xml" />
        <FindDimAsNew site="C:\fkgtest\ELC\local" />
    
</gmBasic>

As will be described below, the site attribute specifies the location of the VBI files to be scanned.

 Move References Reports to Runtime DLL

There is an urgent need to enhance the References reports as requested in an Email.

"Also a question: is it possible to get a report of the specific COM events that have event handlers in a given compilation unit. And if the answer is what I think it is then a request: Reporting event handlers for controls as records with memtype=Lib_Event in the references report would be helpful. Since migrating event handlers is a significant driver of effort for Control replacement, it is important that the migration team get accurate data on what events are handled the during the assessment and planning phase. Right now, the only time memtype=Lib_Event records are created is when the handler is called explicitly. I understand the definition of a handler is not really a reference to the event, but in the spirit of static analysis, it is reasonable to record it as such".

The problems with the reference reports are many. The primary one is that it uses an information stream created by the compiler for use by the analyser for doing type-interences. Any changes made to this stream endanger the overall operation of the tool's primary functions. The secondary one is that reporting is being done within the tool itself; thus, making it inaccessable to the migration specialists. The facility to extend the capabilities of the tool has been implemented for some time via Runtime Dlls; however, to date these Dlls have only been used for doing very low level refactoring work. The goal of this task to extend the capabilities of the tool directly so that it can seamlessly execute commands that are implemented in an external DLL that can coded and managed completely independently of the tool itself. The deliverable of this task is such a runtime DLL that can reproduce exactly what is now done by the Search.References and Search.Definitions commands without using the references information stream produced by the compiler.

The test case that I am using is the small code that was used in the previous task.

  <gmBasic>
     <Storage Action="Create" Identifier="C:\promula\pbasic\GMtest.vbi" />
     <Select DevEnv="VS2010" />
     <Select Dialect="csh" />
     <Select BuildFile="on" />
     <Select ImportsGlobal="off" />
     <Select CheckMultiSet="on" />
     <Select DeployLocation="C:\gmproj\GMTest\deploy\condComp_pro_csh" />
     <Select Library="C:\gmproj\GMTest\deploy\externs" />
     <select Target="C:\gmProj\lab\IDF\FromCode" />
     <Select Local="C:\gmProj\lab\IDF\FromCode" />
     <Select System="C:\gmProj\lab\IDF\FromIdl" />
     <Registry Type="idfstatus" Source="stdole2.tlb" Target="migrate" />
     <Registry Type="idfstatus" Source="MSVBVM60_3.dll" Target="migrate" />
     <Reference id="msacc.olb" />
     <Compile Project="C:\gmSrc\GMTest\AccessDoCmd\AccessDoCmd.vbp" />
     <Analyse />
     <Output Status="New" Filename="GMtest.bnd" />
     <Author>
     </Author>
     <Storage Action="Close" />
  </gmBasic>
I then added a second script.
  <Search Storage="C:\promula\pbasic\GMtest.vbi" Output="GMSearch.txt" >
     <References />
     <Definitions />
  </Search>
The goal then will be repoduce the GMSearch.txt result using an external runtime DLL.

The actual work has taken about two days. There have been a few minor changes made to the tool to extend the list of tool methods called by native dynamic-link-libraries written in C in the file gmsldll.c, to implement a LoadRuntime command that loads a Runtime Dll independently of any RefactorLibraries, and to enhance XeqVB7.LocCommandFile() to check for any Runtine Dlls the can execute a command that it does not recognize itself. The code within the gmslDll subdirectory has been extensively rewritten. I am trying to simplify the notation and generalize it so that it can be used easly. I have started writing a bit of documentation about this under the gmNI but there is much to say. The two new code files added are ReferencesAudit.c and References.c that are used to form the file ReferencesAudit.dll which on my system is stored in my language location.

Here is what the new facility looks like. This is the direct equivalent of the Search script above.

  <pBasic>
     <LoadRuntime dllName="ReferencesAudit.dll" />
     <Storage action="Open" identifier="C:\promula\pbasic\GMtest.vbi" />
     <Output Status="New" Filename="gmRefer.txt" StripTrail="on" />
     <AuditReferences  />
     <AuditDefinitions />
     <Storage Action="Close" />
  </pBasic>
The LoadRuntime looks for the named file using the standard search order. In my case it is stored in the language location. This Dll may well be intermingled with Dlls loaded via the Select RuntineDll command and Dlls loaded via refactoring commands. At the present time there is a maximum of 64. Each DLL exports certain methods that are then looked for by the logic in the tool. In this case ReferencesAudit.c has this method.
  DLL_EXPORT int ExecuteCommand(char* command,int nCommand)
  {
     ...
  }
When XeqVB7.LocCommandFile() encounters a command it does not recognize it calls the method gmslDll.gmslExecuteCommand() which then scans all loaded dlls looking for ones that can execute the command.

Notice next that rather than having a separate Search command that opens storage and outputs, the standard facitilites of the tools runtime engine are used. There was a minor wrinkle with the Output statement. Up until a few years ago the author always stripped trailing blanks from records before writing them, but there was a issue reported for ASP in which the trailing blanks were needed. Rather than arguing the point, I removed the convention and added a flag. Since I am now using the mainline Output statement I added an option to do this. It was needed to get a match on the Definitions report. The AuditReferences and AuditDefinitions reports now produce identical results to their Search equivalents, but in a much more general way. Next, as the following shows

  <pBasic>
     <LoadRuntime dllName="ReferencesAudit.dll" />
     <Output Status="New" Filename="gmRefer.txt" StripTrail="on" />
     <AuditReferences Storage="C:\promula\pbasic\GMtest.vbi" />
     <AuditDefinitions Storage="C:\promula\pbasic\GMtest.vbi" />
  </pBasic>
the commands do support their own Storage attribute. There is often a need to do multiple references reports on different files. This facility allows this. Alternatively one might want to generate one of these reports as part of a translation effort.
  <gmBasic>
     <LoadRuntime dllName="ReferencesAudit.dll" />
     <Storage Action="Create" Identifier="C:\promula\pbasic\GMtest.vbi" />
     <Select DevEnv="VS2010" />
     <Select Dialect="csh" />
     <Select BuildFile="on" />
     <Select ImportsGlobal="off" />
     <Select CheckMultiSet="on" />
     <Select DeployLocation="C:\gmproj\GMTest\deploy\condComp_pro_csh" />
     <Select Library="C:\gmproj\GMTest\deploy\externs" />
     <select Target="C:\gmProj\lab\IDF\FromCode" />
     <Select Local="C:\gmProj\lab\IDF\FromCode" />
     <Select System="C:\gmProj\lab\IDF\FromIdl" />
     <Registry Type="idfstatus" Source="stdole2.tlb" Target="migrate" />
     <Registry Type="idfstatus" Source="MSVBVM60_3.dll" Target="migrate" />
     <Reference id="msacc.olb" />
     <Compile Project="C:\gmSrc\GMTest\AccessDoCmd\AccessDoCmd.vbp" />
     <Analyse />
     <Output Status="New" Filename="GMtest.bnd" />
     <Author>
     </Author>
     <Output Status="New" Filename="gmRefer.txt" StripTrail="on" />
     <AuditReferences  />
     <AuditDefinitions />
     <Storage Action="Close" />
  </gmBasic>
This now produces the same references report after doing the translation. I put the LoadRuntime statement first just to show that it does not interfer with the normal processing of the tool. Clearly this approach is cleaner and easier to use than the Search appoach which I would like to deprecate as soon as possible.

 Add AuditExternals Command to Runtime DLL

The original plan was to try to extend the anarefer.AnalyseReferences() logic to use the logic that determines which external components are referenced to create a new references stream. This approach was ill-advised for the same reasons as above. Risking destabilizing mainline capabilities in the tool to do reporting just makes no sense. The alternative in the runtime DLL code was to copy the method references.LocSimpleSearch() into a method references.LocExtendedSearch() and to gradually expand its capabilities to match those in the AnalyseReferences() logic. A simple script that does the Extended seach looks as follows.
  <pBasic>
     <LoadRuntime dllName="ReferencesAudit.dll" />
     <Storage action="Open" identifier="C:\fkgtest\weldon\csh\Weldon1.vbi" />
     <Output Status="New" Filename="Test.txt" />
     <AuditExternals  />
     <Storage Action="Close" />
  </pBasic>
The simple test code I was using before did not have enough meat to test the things I was planning for the externals report. Note at this point in time I am still reporting all symbol references in this report not just external ones. I would suggest we add a flag for that at some point.

The first step was to search the analysed code as opposed to the compiled code. Generally the results look good. I see no major problems in the source lines being displayed. What is reported is somewhat different. I will let those more used to working with these reports to look for issues -- my eyeballs are happy.

The second step was to search, in addition to SUBPROGRAMS and ASPFILES, CONSTANTS, ENUMENTRY values, and controls. The major addition here are controls and since that code does retain line number information the results look fine. I have no clear examples of CONSTANT and ENUMENTRY code references but some sort of accommodation will have to be made when we find an issue.

The third step was to get a report of the specific COM events that have event handlers in a given compilation unit, reporting event handlers for controls as records with memtype=Lib_Event in the references report. Here the Loc Line, Loc Text information is not available so I am entering the line number as DECL and am using the DesplayDeclaraction logic used in the definitions report as a substitute for the text.

The fourth step was to detect references to things like sysRS!PropertyName = "Node Count" as a field reference.

The fifth step was to pick up references to default item methods in collection classes when the code simply shows an COL.Item reference.

The sixth step was to pick references to components in the MigrationSupport library that were hiding under operations codes.

The AuditExternals command now seems to address every request that is active. My only current feeling is that the AuditDefinitions command have an option that excludes unreferenced components from the list, and the AuditExternals command by default only shows components in IDFs, with an option to show all references as it does now. Until I get further marching orders on this facility I will do nothing more. That said it is my intention to remove the tool contained reference report facilities as soon as possible.

 The gmNI Compiler Events

The code events triggered by the Compile statement are as follows:

Event Description
BeginProperty This event is triggered by the compiler when it encounters a BeginProperty statement in a propery bag specification.
CompileScript This event is trggered by the pass1 compiler when it encounters a JavaScript script. The gmBasic compiler does not compile script files within ASP pages, it simply passes them through.
EditAspSource This event is called when a source file is first loaded so that it can be edited.
EditStatement This event is called each time a new source statement is read. The event handler can then change the content of that statement.
EditProgId This event is called each time the compiler encounters a ProgId in a CreateObject statement. The event handler can then change the content.
EditProperties This event is triggered by the first pass of the compiler immediately after it opens the property-bag source code.
StartPass2 This event is triggered immedialely after the first pass but before the compiler generates any code or does any type inference.
UndefinedProperty This event is triggered whenever the compiler encounters an undefined property name while compiling a propery bag specification. The handler can then try to resolve it.


 The gmNI Analyser Events

The code events triggered by the Analyse statement are as follows:

Event Description
AdjustChildren This event is triggered when processing a control that is the child of a control being migrated.
AdjustProperties This event is triggered when processing the properties associated with a control.
CheckSelect This event is triggered immediately before the analyser branches to either convert a VB6 Select to an if or to fix it so it can become a C# switch statement. VB6 Select statements have often required special processing in the user code.
CodeEvent This event is triggered first during the initialization phase and second during the code review phase for each code block in the current scope of the analyzer by references in the code to subcomponents that have a migUserCode value attributed to them. This is normally done with the Migrate command within a Refactor specification.
CodeScan This event is called three times for each code component with out requiring any user supplied annotations to that component: first, during the initial processing of the code; second, during the intermediate processing of the code; and third, during the final processing of the code. CodeEvents are triggered by references to components, while CodeScans are triggered by the code containing components themselves.
FinishAnalyser This event is triggered once after all other processing in the analyser has been completed.
StartAnalyser This event is triggered once before any other processing within the analyser. It is typically used to the mark those components that are to trigger later transform events.
Transform This event is triggered during the final analysis phase for each code block in the current scope of the analyzer by references in the code to subcomponents that have been marked as requiring special processing. This mark is typically applied by a StartAnalyser event handler.


 The gmNI Author Events

The code events triggered by the Author statement are as follows:

Event Description
AuthorClass This event is triggered immediately before the definition of a class is authored to obtain an optional ServiceName string. If the class requires "System.Runtime.InteropServices" then this string contains the service name.
AuthorClassFile This event is triggered twice while ASP code-behind classes are being authored: first, immediately before the interface for the class is authored; and second, before the implements description is written.
AuthorDeclare This event is triggered by author when a control is being declared or allocated. The event is used to generate special declarations and allocations for migrated controls.
AuthorDeclaration This event is triggered immediately prior to authoring the declaration for a component. It can be used to author an alternative declaration.
AuthorLibraryStub This event is triggered after the component stubs for a given library have been authored. It can be used to add any additional stubs needed.
AuthorNetControl This event is triggered by the author immediately before and after it authors control properties using a migClass specification. It is used to enter specifications in the designer file for the control.
AuthorProjectFile This event is triggered immediately before the project and assembly files are authored for the translation code set. If used, what is authored completely replaces the standard project and assembly files.
AuthorProperties This event is triggered after the properties associated with a control have being authored. It is used to add additional property information to that control.
AuthorReference This event occurs when the author is writing a project file immediately before writing the list of external references needed by project. It is used to change how the reference is to be written.
ControlIsMigrated This event is triggered when the author needs to know if a control is being migrated.
GetSpecialName This event is triggered when a the classname of a user class is being authored. It is use to get any special name that may be needed for the class if it is implemented.
CallLateBinding This event is triggered when interfaces are being authored for CallBack components. it is used to get the interface declaration and interface attribute strings.


 The gmNI Service Classes

The problem dealt with via the runtime services is that the migration DLL's must deal directly with the information storage being managed by the translation tool. If these DLLs were to call the various utilities directly, they would be dealing with their own copies of that information which would be different. MicroSoft says "Warning, There are serious limits on what you can do in a DLL entry point. To provide more complex initialization, create an initialization routine for the DLL. You can require applications to call the initialization routine before calling any other routines". The runtime services are provided to DLL's via an InitializeServices() method that is called immediately after the DLL is loaded.

he runtime services are organized into a set of classes. Each class contains only methods:

Class Description
Author Component authoring utiliyies
Compile Access to the compile2
DataQueue Access to the runtime data queue
List Standard list processing
Meta Meta language information
Opcode Working with the intermediate language streams
Registry Accessing the registry
Script Working with commabd script files
Select Obtaining the current set of selected attribute values
Source Tokenizing the current source input text buffer
String String manipulation
Store Working with the storage areas
Symbol Working with the symbol table
System Accessing files in the system
Text Access to text buffers
Write Formatted write utilities


 Author Service Class

The Author service class contains component authoring utilities.

 Author_BaseType Method

gmSL: void AuthorBaseType(int binaryType, int targetLang)
gmVB: Sub AuthorBaseType(ByVal binaryType As Integer, ByVal targetLang As Integer)
gmNI: void AuthorBaseType(int binaryType, int targetLang)

This method authors the identifier of a base type either in one of the translation target languages -- C#, VB.NET, or gmPL. The output produced is entered directly into the current output record.

binaryType is the code for the base type. If this less the the maximum number of operation codes then the type has a language possibly dependent identifier--see OPC_TYP. Otherwise it equals the storage handle of a user or library symbol.

b>targetLang is the code for the desired target language. The following are supported: LNG_CSHARP, NG_VBNET, LNG_SCRIPT.


 Author_CodeStream Method

Author_CodeStream

 Author_ExternalStubs Method

Author_ExternalStubs

 Author_GetTypeString Method

Author_GetTypeString

 Author_InitValue Method

Author_InitValue

 Author_Interface Method

Author_Interface

 Author_InterfaceEntry Method

Author_InterfaceEntry

 Author_Pattern Method

Author_Pattern

 Author_ProjectCompileIncludes Method

Author_ProjectCompileIncludes

 Author_ProjectExternals Method

Author_ProjectExternals

 Author_SetVbName Method

Author_SetVbName

 Author_SupportReference Method

Author_SupportReference

 Author_Type Method

Author_Type

 The Compile Service Class

The Compile servive class gives access to the compiler passes.

Compile_Pass1

Compile_Pass2


 The DataQueue Service Class

The DataQueue class supports a LIFO (Last In First Out) list of temporary arbitrary data items used both by the runtime engines and string machines. All data stored in the queue is in raw form followed by a two word record which contains the length of the information in words and a type code which describes the type of information stored. The base if the queue contains three values: the total size, the current top, and the current local base.

The DataQueue_ClearBottom method

The DataQueue_ClearBottom method clears the current queue bottom.

void RdqClearBottom(int isEmpty):

Argument Description
isEmpty If this is non-zero then the queue must be positioned at the bottom; else this service empties the queue.

This method checks to see if there is a bottom mark at the current top of the queue. If there is, then it removes that mark. If there is not a botttom mark at the top of the queue, then it either clears the queue or issues a fatal system error.

The DataQueue_GetInteger Method

The RdqGetInteger method gets an integer value from the queue.

int RdqGetInteger()

This method examines the current top of the queue. If an integer value is stored there then it is removed from the queue and returned. If there is a string value at the top of the queue, then it is converted into integer form and returned. If the queue is currently empty or is positioned on a bottom mark, then a zero is returned.

DataQueue_GetString

DataQueue_PushInteger

DataQueue_PushString

DataQueue_SetBottom


 The List Service Classes

The List service class does standard list processing

List_AddEntry

List_FindByName


 The Meta Service Classes

The Meta service class works with Meta language information

Meta_LoadObjectModel

Meta_RunMethod

Meta_UseTemplate


 The Opcode Service Class

The Opcode service class works with the intermediate language streams

Opcode_AddTemporary

Opcode_AddVariable

Opcode_AdjustSubscript

Opcode_ArgCallTypes

Opcode_DeleteCode

Opcode_DumpCode

Opcode_ExpandCode

Opcode_GetArgumentType

Opcode_GetCallArgs

Opcode_GetCode

Opcode_GetLength

Opcode_GetMember

Opcode_GetNext

Opcode_GetPrevious

Opcode_GetStackLevel

Opcode_GetSubcodeLabel

Opcode_FindArgEnd

Opcode_IntegerValue

Opcode_MoveCode

Opcode_MoveSelectCode

Opcode_SetLength

Opcode_StringValue

Opcode_TraverseArgs

 Opcode_GetInfo Method

gmSL: tOpcInfo Opcode_GetInfo(int opcValue)
gmVB: Function Opcode_GetInfo(ByVal opcValue As Integer) As tOpcInfo
gmNI: UBYTE* Opcode_GetInfo(int opcValue);

This method returns a handle to a packed tOpcInfo structure in the language file that contains the basic information for a particular opcode given its numeric index via the opcValue parameter. The content of this structure is as follows:

Member Description of content
length The overall length of the packed information structure if bytes
ident The identifier of the opcode in nul-terminated form. Note that the opcode identifiers are always three uppercase character strings.
value The actual numeric value of the opcode. This is the value used to identify it via the opcValue parameter.
type This is an entry value from the opcTypes enumeration which describes the physical type of the opcode.
role This is an entry value from the opcRoles enumeration which decribes the overall role of the opcode.
subcodes This is the number of subcodes associated with the opcode
sublist This is the root offset in packed language storage of the standard list of subcodes associated with this opcode.
interface This is the root offset in the language symbol table of the class that describes the subcodes of the opcode.

As an example, the following method using gmVB syntax audits the information for a given opcode.

 Sub OpcodeInformation(ByVal opcValue As Integer)
    Dim opcInfo As tOpcInfo

    opcInfo = Opcode_GetInfo(opcValue)
    Write_Text "The Opcode " & opcInfo.ident & " has value " & opcInfo.value
    Write_Record
    Write_Text "   length    = " & opcInfo.length
    Write_Record
    Write_Text "   ident     = " & opcInfo.ident
    Write_Record
    Write_Text "   value     = " & opcInfo.value
    Write_Record
    Write_Text "   type      = " & Symbol_NamedEntryLabel("opcTypes",opcInfo.type)
    Write_Record
    Write_Text "   role      = " & Symbol_NamedEntryLabel("opcRoles",opcInfo.role)
    Write_Record
    Write_Text "   subcodes  = " & opcInfo.subcodes
    Write_Record
    Write_Text "   sublist   = " & opcInfo.sublist
    Write_Record
    Write_Text "   interface = " & opcInfo.interface
    If opcInfo.interface Then
       Write_Text " : Class = "
       Author_BaseType(-opcInfo.interface,Select.Dialect)
    End If
    Write_Record
 End Sub

Then the gmPL statement

 <RunCommand Id="scmDemo.OpcodeInformation"  prams="170"/>
generates the following output
 The Opcode USC has value 170
    length    = 17
    ident     = USC
    value     = 170
    type      = DoubleByte
    role      = Clsref
    subcodes  = 128
    sublist   = 58067
    interface = 302663 : Class = UserControl


 The Registry Service Classes

The Registry service class accesses the registry.

Registry_GetNameValue


 The Script Service Classes

The Script service class works with command script files.

Script_FixFile

The Script_GetContent Method

The Script_GetContent method gets the attribute string values of an Xml script statement.

int XmlGetContent(char* statement, UBYTE* Attributes, char** content):

Argument Description
statement This null-terminated string contains the actual XML statement to be parsed. Note that as information is isolated in this statement it is null-terminated within the statement itself; therefore, a constant string must not be passed.

Attributes Contains the list of attributes structured as described in the description of this method.

content This vector returns pointers to the value(0) substring and attribute information values within the statement. These substrings are null-terminated. Word zero contains the content pointer and words 1+ correspond to the attributes as they are identified in their list. If a given entity has no associated substring a NULL is entered. An XML statement is a component of a valid XML document which is in one of two possible forms:

  •  <tag .../>
       or
    
In each case, the "..." refers to a possibly empty set of attributes separated by blanks. Each attribute has the form
  attribute(i)="value(i)"
There is a special attribute notation referred to as an empty attribute which has the form
    attribute="attribute"
When the form is used then there is no value(0). When the full notation is used then value(0) is optional.

The list of possible attributes is stored in as a standard list with a count byte at the front followed by a sequence of entries in the following form:

Cell Description of content
0 Length of the entry for the current attribute
1+ The actual characters making up the attribute identifier in null- terminated form.
2 The attribute identification code, i.e. is a sequence number starting at one.
3 An attribute type designation that is not used by this service.

If an error is encountered, then this method returns the error code; else it returns zero.

Script_GetRecord

Script_ReadRaw

Script_ReadRecord

Script_RestoreInfo

Script_RunCommand

Script_SaveInfo

Script_UseStream

 The Select Service Class

The Select service class obtains the current set of selected attribute values

Select_GetFlags


 The Source Service Classes

The Source tokens the current source input text buffer

Source_Insymbol

Source_LookAhead


 The String Service Class

The String string class does string manipulation

String_ApplyTemplate

The String_Compare Method

The String_Compare does a comparison between two strings.

int ChrCompare(char* s1, char* s2, int ns) :

Argument Description
s1 Points to the first string in the comparison.
s2 Points to the second string in the comparison.
ns Specifies the number of character to be compared.

This method does a case-insensitive comparison between two strings. This is a bounded search. The null-character is treated exactly like any other special character. If all characters within the specified range are identical, upto case distinctions, then the method returns a zero. If two characters within the specified range disagree, then the value of the character in the first string minus that in the second string is returned.

String_CompareStrings

String_ConvertCase

String_Edit

String_FindFirst

String_FromShort

String_HexiDecimal

String_ShiftLeft

String_ShiftRight

String_ToShort


 The Store Service Class

The Store Service class works with the storage areas

Store_AddGlobal

Store_Close

Store_Create

Store_DeltaVector

Store_FindFirstChild

Store_FindNextChild

Store_FindLibVector

Store_FindVector

Store_FirstReference

Store_GetDataName

Store_GetHandle

Store_GetIdent

Store_GetLength

Store_GetName

Store_GetNext

Store_GetParent

Store_GetString

Store_GetVector

Store_NextReference

Store_Open

Store_Reference

Store_RewriteInfo

Store_Select

Store_SetName

Store_SetObjectType

Store_SetString

Store_String

Store_Unit

Store_Vector

Store_WriteInfo

 GetFirst Method

Synopsis: int GetFirst(int parent)

This method returns the first child of a parent component or of the root branch. This is the first component entered for the parent. In general, using this method in conjunction with the GetNext method, will generate the sequence of components stored within some branch of the symbol table in their defined order. parent contains the root offset of the parent component or zero if the first member of the root branch in the symbol table is desired.

If there is a first child of the specified component then this method returns its root offset. If there is no first child then this method returns a zero.

 GetNext Method

Synopsis: int GetNext(int child)

This method returns the next child of a parent component or of the root branch. This is the next component entered for the parent. In general, using this method in conjunction with the GetFirst method, will generate the sequence of components stored within some branch of the symbol table in their defined order. child contains the root offset of the current child component as returned by GetFirst or a previous call to GetNext.

If there is a next child of the parent of the specified component then this method returns its root offset. If there is no next child then this method returns a zero.

 GetObjectType Method

Synopsis: int GetObjectType(int root)

Whenever a component is entered into the symbol table it is assigned and integer object type code. Each object type code has associated with it a fixed-length information vector used to describe components of the specified type. In the case of gmBasic the type code is either an entry number from the ObjectType enumeration in the language file, the opcode value of a built-in class if the component is a built-in control, or the root offset of an external class if the object is a control of that external class.

root contains the root offset of component in storage. If root has a value less than or equal to zero, then this method displays the following message and returns a zero.

   SYSERR#5001: Object Type requested for invalid root %root%
If root has a value that exceeds the maximun possible offset, this methode displays the following message and returns a zero.
   SYSERR#5002: Object Type requested for invalid root %root%

If root is not obviously malformed this method returns the object type code in the symbol table entry at the specified root offset.

 ReadInfo Method

Synopsis(gmNI): int ReadInfo(void* info, int offset)
Synopsis(gmSL): int ReadInfo(int icode, int offset)

This method reads long blocks of information that were initially written using the method WriteInfo. A physical read is required, since these information vectors may cross block boundaries, thus making simple pointers inappropriate. Within gmSL this method can only be used to read code blocks into the code storage area reserved by gmBasic and allocated by the Select CodeSize attribute; therefore, icode is the starting offset into this area. Within gmNI other information vectors can be read as well; therefore, info is simply a pointer to a typeless area of memory. The equivalent of gmSL

   Store.ReadInfo(icode,offset)
in gmNI is
   Store_ReadInfo(codptr+icode,offset)

offset contains the starting offset of the information as originally returned by the WriteInfo method. The method the length of the information block read in bytes.

 The Symbol Service Class

The Symbol Service class Works with the symbol table

Symbol_FindClass

Symbol_FindIdentifier

Symbol_FindInLibraries

Symbol_FindProperty

Symbol_FullName

Symbol_FullType

Symbol_GetDefault

Symbol_MetaIdentifier

Symbol_NamedEntryLabel

Symbol_PropertyValue

Symbol_StorePattern

Symbol_SurfacePattern

Symbol_WriteNamedFlags


 Unused

Synopsis: int Unused(int iRoot)

The compiler after it processes a subprogram, a property method, or an ASP page, scans the intermediate code produced and produces a sorted symbol reference list. iRoot is the root offset of a symbol. This method checks the sorted symbol reference list to see if it contains any record for iRoot. If it does, then the symbol is used somewhere in the code, and this method returns zero; else the symbol is unused and this method returns one.

 The System Service Classes

The System service class accesses files in the system

System_MakeFileName

System_ParseFileName


 The Text Service Class

The Text service class gives access to text buffers

Text_Access

Text_BeforeTop

Text_Close

Text_Create

Text_Current

Text_Delete

Text_Expand

Text_FindFiles

Text_GetToken

Text_Increment

Text_Insert

Text_LoadFile

Text_Location

Text_Maximum

Text_Open

Text_Position


 The Write Service Class

The Write service class contains the basic methods needed to write structured reports and text files of various sorts using binary information. It is used very extensively by gmBasic during every phase of its operation and is fully exposed via gmSL. Ultimately, at any given point in time, only one coded output report can be written at one time. Logically, a structured text output, be it a free-form text representation or a tabular representation containing fixed fields, is viewed as having four levels:

Level Description
File There are 5 totally independent file structures that may be in use. Initially only 1 of these, unit 1, is active. It is managed via the gmPL Output statement. Internally, gmBasic uses unit 5 as a scratch output file. This unit is never left open outside of a given task within the process. The other units are available as needed. (Note to tool implementers that there is a constant WRT_PROVIDERS, currently set to 5, that may be changed when doing a tool build. It is unit 1 and unit WRT_PROVIDERS whose use is restricted to gmBasic.) Each file has a physical file associated with it, which is either a named file or the Standard Output file. At any given point in time only one file unit is active, unit 1 is always the default, and all write operations are performed on that unit. The term selected unit is used to refer to the currently active one.
Stream By default records are written to the physical file associated with the selected unit; however, in many cases what is needed is an internal representation of what is to be written to the file. This representation, referred to as a text stream, can then be saved, edited, audited, and perhaps eventually physically written to a file. At any point in time, the selected unit is either writing to its physical file or to a text stream. During its life a file unit can spawn as many text streams as desired, but can only process one at a time.
Record Each file unit has a record buffer associated with it. This buffer stores the characters being written until it is physically written to the active stream or is disposed of in some other manner such as being copied to the runtime data queue. Low level methods in this service class all add their output to the record associated with the selected unit. The records in the different units are completely independent of each other. The maximum number of characters that may stored in a record at one time is 8192. (Note to tool implementers there is a constant MAX_BUFFER that defines this value.)
Field Ultimately each method that adds characters to a record is said to be "writing a field" at the back of the record of the selected unit. Characters can be entered into fields either free-form, or left-justified in a fixed-width field with a white space to the right, or right-justified in a fixed-width field with white space to the left.

In addition, there is also a log file maintained by gmBasic. This file receives all messages -- progress, warning, error, etc. -- written during a given run. By default it is simply the Standard Output file; however, it may be connected to any named file. When connected to a named file, that file is opened for append access prior to each write and is then closed after the write. This ensures that no output sent to the log file is lost in cases where abnormal exits are occurring.

 Write_ChangeMargin Method

gmSL: void Write_ChangeMargin(int delta)
gmVB: Sub Write_ChangeMargin(ByVal delta As Integer)
gmNI: void Write_ChangeMargin(int delta);

When authoring gmBasic does not attempt to reproduce the leading white space in the source code; rather, it keeps track of the margin nesting level via the p and q escape characters in the surface patterns or via calls to this method and then uses this margin level times the indentation width specified via the Select Indent attribute to determine the number of leading blanks or tabs to add.

This method adds the value of delta to the current margin level. If delta is negative, the indentation will be decreased, and if it is positive, the indentation will be increased. If the computed margin level ends up being negative, it is set back to zero.

As an example, the following method displays un indented and indented lines.

 void DemoWriteChangeMargin(string comment)
 {
    Write_Line("Unindented Line: " + comment);
    Write_ChangeMargin(1);
    Write_Line("Indented Line: " + comment);
    Write_ChangeMargin(-1);
    Write_Line("Unindented Line: " + comment);
 }
Then the gmPL statements
 <Select Indent="3" />
 <Output Status="New" Filename="Demo001.out" />
 <RunCommand Id="scmCode.DemoWriteChangeMargin"  prams="Indent is selected at 3"/>
 <Select Indent="8" />
 <Output Status="Old" Filename="Demo001.out" />
 <RunCommand Id="scmCode.DemoWriteChangeMargin"  prams="Indent is selected at 8"/>
 <Select Indent="0" />
 <Output Status="Old" Filename="Demo001.out" />
 <RunCommand Id="scmCode.DemoWriteChangeMargin"  prams="Indent is selected at 0"/>
generate the following output
 Unindented Line: Indent is selected at 3
    Indented Line: Indent is selected at 3
 Unindented Line: Indent is selected at 3
 Unindented Line: Indent is selected at 8
         Indented Line: Indent is selected at 8
 Unindented Line: Indent is selected at 8
 Unindented Line: Indent is selected at 0
 	Indented Line: Indent is selected at 0
 Unindented Line: Indent is selected at 0
Note that the value of the selected indent is applied when the output file is opened. Using the Old status forces this open to occur while still writing to the back of the file.

 Write_Character Method

gmSL: void Write_Character(int charValue)
gmVB: Sub Write_Character(ByVal charValue As Integer)
gmNI: void Write_Character (int charValue);

This method appends the ASCII character whose display code is specified by charValue to the current output record. No actual write occurs at this time.

Note that if called from gmSL with a string argument, the string is not converted to an integer as would be the normal convention; rather, the value of the first character in the string is passed.

As an example the following displays a character value

 Sub DemoWriteCharacter(ByVal theCharacter)
    Write_Text "Character Value is: "
    Write_Character(theCharacter)
    Write_Record
 End Sub
Note that the parameter theCharacter is not typed in the code; therefore, it will take on its type based on the type of the argument passed in as shown in the following
 <Output Status="New" Filename="Demo002.out" />
 <RunCommand Id="vbCode.DemoWriteCharacter"  prams="65"/>
 <RunCommand Id="vbCode.DemoWriteCharacter"  prams="F"/>
 <RunCommand Id="vbCode.DemoWriteCharacter"  prams="'65'"/>
which produces the following output
 Character Value is: A
 Character Value is: F
 Character Value is: 6
A is the character with display code 65; whereas the string '65' simply has its first character displayed.

 Write_CloseFile Method

gmSL: void Write_CloseFile()
gmVB: Sub Write_CloseFile()
gmNI: void Write_CloseFile(void);

The Write_CloseFile method closes the selected unit and any physical file associated with that unit. Upon completion, unit 1, the unit associated with the gmPL Output statement, becomes the selected unit.

The following code opens and writes records to three different files -- two files that it maintains under units 2 and 3 and the file associated with the Output statement. The important point made in this example are the two writes done after the file closings. It is these writes that go to the Output file.

 void DemoWriteSelect(string file1,string file2)
 {
    Write_OpenFile(2,file1,True,OutStyle.Text);
    Write_OpenFile(3,file2,True,OutStyle.Text);
    Write_Select(2);
    Write_Line("Line 1 in File " + file1);
    Write_Select(3);
    Write_Line("Line 1 in File " + file2);
    Write_Select(2);
    Write_Line("Line 2 in File " + file1);
    Write_CloseFile();
    Write_Line("Line 1 in Output File");
    Write_Select(3);
    Write_Line("Line 2 in File " + file2);
    Write_CloseFile();
    Write_Line("Line 2 in Output File");
}
The following gmPL statements then write output to three different files.
 <Output Status="New" Filename="Demo017.out" />
 <RunCommand Id="scmCode.DemoWriteSelect" prams="Demo017A.out;Demo017B.out" />
and the results are as expected. The file Demo017A.out contains
 Line 1 in File Demo017A.out
 Line 2 in File Demo017A.out
and file Demo017B.out contains
 Line 1 in File Demo017B.out
 Line 2 in File Demo017B.out
and file Demo017.out, the Output file contains
 Line 1 in Output File
 Line 2 in Output File

 Write_CloseStream Method

gmSL: int Write_CloseStream()
gmVB: Function Write_CloseStream() As Integer
gmNI: int Write_CloseStream(void);

In gmBasic authored records are stored in text buffers within the current storage area. The CloseStream method closes the currently open text buffer and returns its integer handle. This handle must be saved by the caller to be used later to either reopen the text buffer or to physically write it to a file. If writes are currently being sent directly to the file specified in the Output statement, then this method does nothing.

The following code shows how text buffers as used.

 void DemoWriteTextStreams(string theAuthor)
 {
    int textRoot;
    Handle textStream;

    Write_Line("Write record to Output file before opening a text buffer");
    Write_OpenStream();
    #TextStart
    Hello World
       This is a message from (%= theAuthor %)
    GoodBye World
    #TextEnd
    textRoot = Write_CloseStream();
    Write_Line("Write another record then write content of text buffer");
    textStream = Text_Open(Store_GetHandle(),textRoot);
    Write_TextStream(textStream,0,0);
    Text_Close(textStream);
 }
The records both before and after the write to the text buffer go to the Output file before the buffer itself is written using the Write_TextStream() method. Note it is the return value from this method that is needed to open the text buffer for later use. This code then
 <Output Status="New" Filename="Demo003.out" />
 <RunCommand Id="scmCode.DemoWriteTextStreams"  prams="Kilroy"/>
produces the following output.
 Write record to Output file before opening a text buffer
 Write another record then write content of text buffer
 Hello World
    This is a message from Kilroy
 GoodBye World
Notice also that the #TextStart .. #TextEnd block behaves in the same manner as text written explicitly using the Write service class.

 Write_Field Method

gmSL: void Write_Field(string strValue, int nString, int iField)
gmVB: Sub Write_Field(ByVal strValue As String, ByVal nString As Integer, ByVal iField As Integer)
gmNI: void Write_Field(char* strValue, int nString, int iField);

This method is the lowest level utility within the Write service class. It appends a specified field of characters to the current output record. No actual write occurs at this time. Within that field the content of strValue may be preceded or followed by white space. nString specifies the number of characters from strValue that are to be used. iField specifies how the characters from strValue should be entered:

Value Meaning
0 Simply append the characters to the current content of the output record.
+n Right justify the characters in a field n characters wide appended to the back of the current record.
-n Left justify the characters in a field n characters wide appended to the back of the current record.

Note that when called via gmSL if nString is set to zero, then the length of the string will be used.

The following code uses this method to display a string in various ways

 void DemoWriteField(string aLongString)
 {
    Write_Field(aLongString,0,0);
    Write_Record();
    Write_Field(aLongString,5,0);
    Write_Record();
    Write_Text("LEFT(");
    Write_Field(aLongString,10,-12);
    Write_Text(")RIGHT");
    Write_Record();
    Write_Text("LEFT(");
    Write_Field(aLongString,10,12);
    Write_Text(")RIGHT");
    Write_Record();
 }
When called as follows
 <Output Status="New" Filename="Demo004.out" />
 <RunCommand Id="scmCode.DemoWriteField"  prams="Kilroy was here"/>
it produces this output
 Kilroy was here
 Kilro
 LEFT(Kilroy was  )RIGHT
 LEFT(  Kilroy was)RIGHT

 Write_Integer Method

gmSL: void Write_Integer(int iValue, int iField)
gmVB: Sub Write_Integer(ByVal iValue As Integer, ByVal iField As Integer)
gmNI: void Write_Integer(int iValue, int iField);

This method appends the base 10 display form of iValue in a specified field of characters to the current output record. No actual write occurs at this time. No special formatting flags are available. iField specifies how the characters of the display form should be entered:

Value Meaning
0 Simply append the characters to the current content of the output record.
+n Right justify the characters in a field n characters wide appended to the back of the current record.
-n Left justify the characters in a field n characters wide appended to the back of the current record.

The following code uses this method to display an integer value in various ways

 void DemoWriteInteger(int iValue)
 {
    Write_Text("LEFT(");
    Write_Integer(iValue,0);
    Write_Text(")RIGHT");
    Write_Record();
    Write_Text("LEFT(");
    Write_Integer(iValue,-10);
    Write_Text(")RIGHT");
    Write_Record();
    Write_Text("LEFT(");
    Write_Integer(iValue,10);
    Write_Text(")RIGHT");
    Write_Record();
 }
When called as follows
 <Output Status="New" Filename="Demo005.out" />
 <RunCommand Id="scmCode.DemoWriteInteger" prams="12345" />
it produces this output
 LEFT(12345)RIGHT
 LEFT(12345     )RIGHT
 LEFT(     12345)RIGHT

 Write_Line Method

gmSL: void Write_Line(string strValue)
gmVB: Sub Write_Line(ByVal strValue As String)
gmNI: void Write_Line(char* strValue);

This method appends all characters from strValue to the current output record and then writes the result either to the currently open text buffer or to the file specified in the Output statement. No formatting is applied to the string.

The following code contrasts using a TextBlock versus using Write_Line() and Write_ChangeMargin().

 void DemoWriteLine(string theAuthor)
 {
    #TextStart
    Hello World
       This is a message from (%= theAuthor %)
    GoodBye World
    #TextEnd
    Write_Line("Hello World");
    Write_ChangeMargin(1);
    Write_Line("This is a message from " + theAuthor);
    Write_ChangeMargin(-1);
    Write_Line("GoodBye World");
 }
When called as follows
 <Output Status="New" Filename="Demo007.out" />
 <RunCommand Id="scmCode.DemoWriteLine" prams="Kilroy" />
it produces this output
 Hello World
    This is a message from Kilroy
 GoodBye World
 Hello World
    This is a message from Kilroy
 GoodBye World

 Write_LogMessage Method

gmSL: void Write_LogMessage(string message)
gmVB: Sub Write_LogMessage(ByVal message As String)
gmNI: void Write_LogMessage(char* message)

The Write_LogMessage method writes a string message to the file. This is the same file used by gmBasic for its messages. The following gmPL script shows how this method might be used to debug a malfunctioning script.

 <gmBasic>
    <Storage Action="Create" />
    <gmsl>Write_LogSetName("Demo018.log")</gmsl>
 <gmsl>Write_LogMessage("<!-- translation options ")</gmsl>
    <Select progress="1" />
    <Select DevEnv="VS2010" />
    <Select Dialect="csh" />
    <Select BuildFile="global" />
 <gmsl>Write_LogMessage("<!-- directories for deployment and external assemblies -->")</gmsl>
    <Select DeployLocation="c:\gmProj\lab\deploy\externs\CrashV1003_csh" />
    <Select Library="c:\gmProj\lab\deploy\externs" />
    <select Target="c:\gmProj\lab\idf\FromCode" />
    <Select Local="c:\gmProj\lab\idf\FromCode" />
    <Select System="c:\gmProj\lab\idf\FromIdl" />
 <gmsl>Write_LogMessage("<!-- processing commands -->")</gmsl>
    <Compile Project="c:\gmSrc\GMTest\CrashV1003\CrashV1003.vbp" />
    <gmsl>Write_LogSetName(Null)</gmsl>
    <Analyse />
 <gmsl>Write_LogMessage("<!-- authoring commands -->")</gmsl>
    <Output Status="New" Filename="Demo018.bnd" />
    <Author />
    <Storage Action="Close" />
 <gmsl>Write_LogMessage("<!-- End of script -->")</gmsl>
 </gmBasic>
Note first of all, that gmSL command mode is being used in this script. Though the logging methods can be used in runtime code as desired for messages, they are also ideal for direct use within scripts. Running this script produces this Demo018.log file
 <!-- translation options
 <!-- directories for deployment and external assemblies -->
 <!-- processing commands -->
 Processing file: c:\gmSrc\GMTest\CrashV1003\CrashV1003.vbp
 Loading reference:[stdole2.tlb] c:\gmProj\lab\idf\FromIdl\stdole2.tlb.xml
 Loading reference:[scrrun.dll] c:\gmProj\lab\idf\FromIdl\scrrun.dll.xml
 Reprocessing file: c:\gmSrc\GMTest\CrashV1003\clsCrashV1003.cls
 Reprocessing file: c:\gmSrc\GMTest\CrashV1003\clsCrashV1003.cls
and then sends these remaining messages to Standard output.
 <!-- authoring commands -->
 <!-- End of script -->
Note that the messages written by this method coexist with the messages written by gmBasic and both use the same file.

 Write_LogSetName

gmSL: void Write_LogSetName(string fileName)
gmVB: Sub Write_LogSetName(ByVal fileName As String)
gmNI: void Write_LogSetName(char* fileName)

The Write_LogSetName methods sets a fileName for the file to receive all messages -- progress, warning, error, etc. -- written during a given run. It also receives all messages written via the Write_LogMessage() method. By default log messages are simply written to the Standard Output file; however, when set to a named file, that file is opened for append access prior to each write and is then closed after the write. This ensures that no output sent to a named log file is lost in cases where abnormal exits are occurring. To set the log file back to using Standard Output pass it either Null or Nothing.

The following script reproduced from the discussion of the Write_LogMessage() shows these two types of calls.

 <gmBasic>
    <Storage Action="Create" />
 <gmsl>Write_LogSetName("Demo018.log")</gmsl>
    <gmsl>Write_LogMessage("<!-- translation options ")</gmsl>
    <Select progress="1" />
    <Select DevEnv="VS2010" />
    <Select Dialect="csh" />
    <Select BuildFile="global" />
    <gmsl>Write_LogMessage("<!-- directories for deployment and external assemblies -->")</gmsl>
    <Select DeployLocation="c:\gmProj\lab\deploy\externs\CrashV1003_csh" />
    <Select Library="c:\gmProj\lab\deploy\externs" />
    <select Target="c:\gmProj\lab\idf\FromCode" />
    <Select Local="c:\gmProj\lab\idf\FromCode" />
    <Select System="c:\gmProj\lab\idf\FromIdl" />
    <gmsl>Write_LogMessage("<!-- processing commands -->")</gmsl>
    <Compile Project="c:\gmSrc\GMTest\CrashV1003\CrashV1003.vbp" />
 <gmsl>Write_LogSetName(Null)</gmsl>
    <Analyse />
    <gmsl>Write_LogMessage("<!-- authoring commands -->")</gmsl>
    <Output Status="New" Filename="Demo018.bnd" />
    <Author />
    <Storage Action="Close" />
    <gmsl>Write_LogMessage("<!-- End of script -->")</gmsl>
 </gmBasic>

 Write_NText Method

gmSL: void Write_NText(string strValue, int nText)
gmVB: Sub Write_NText(ByVal strValue As String, ByVal nText As Integer)
gmNI: void Write_NText(char* strValue, int nText);

This method appends the first nText characters from strValue to the current output record. No actual write occurs at this time. No formatting is applied to the string. Note that care must be taken that nText does not exceed the length of strValue. Since gmSL supports a string type, this method is rarely needed. It is intended primarily for use by gmNI.

The following code uses this method to display an a string value fully and in truncated form

 void DemoWriteNText(string aLongString)
 {
    Write_Text(aLongString);
    Write_Record();
    Write_NText(aLongString,5);
    Write_Record();
 }
When called as follows
 <Output Status="New" Filename="Demo006.out" />
 <RunCommand Id="scmCode.DemoWriteNText" prams="Kilroy was here" />
it produces this output
 Kilroy was here
 Kilro

 Write_OpenFile Method

gmSL: void Write_OpenFile(int unit, string fileName,bool statusNew,gmsl.OutStyle syntax)
gmVB: Sub Write_OpenFile(ByVal Unit As Integer,ByVal fileName As String,
ByVal statusNew As Boolean,ByVal Syntax As Integer)
gmNI: void Write_OpenFile(int unit, char* fileName,int statusNew,int syntax);

There are 5 totally independent file structures that may be in use. The Write_OpenFilegmPL Output statement which uses unit 1.

The Unit parameter specifies which file unit is to be used. It must be a value between 1 and 5, though as the example below will show using unit 1 is equivalent to using the Output statement. The fileName parameter is the name of the file to be opened, and the statusNew parameter, if True request that a new file be created as opposed to opening an existing file for append access. The syntax parameter specifies the output style to be used when producing tabular reports. They can be produced in one of three styles: Tabbed simple tab delimited; Text text tabular; or Html html tabular.

The procedure below sows a simple method that could be used as a replacement for the gmPL Output statement.

 void DemoWriteOpenFile(string fileName, bool statusNew)
 {
    Write_OpenFile(1,fileName,statusNew,OutStyle.Text);
 }
and when used as follows
 <gmBasic>
 <Storage Action="Create" />
 <Select GlobalSettings="GmslCode.vbi" />
 <LoadEnvironment />
 <RunCommand Id="scmCode.DemoWriteOpenFile" prams="Demo016.out;.T." />
 <RunCommand Id="vbCode.DemoWriteCharacter"  prams="65"/>
 <RunCommand Id="vbCode.DemoWriteCharacter"  prams="F"/>
 <RunCommand Id="vbCode.DemoWriteCharacter"  prams="'65'"/>
 <Storage Action="Close" />
 </gmBasic>
produces the same output as the statement
 <Output Status="New" Filename="Demo016.out" />
would have produced.

 Write_OpenStream Method

gmSL: void Write_OpenStream()
gmVB: Sub Write_OpenStream()
gmNI: void Write_OpenStream(void);

In gmBasic authored records are stored in text buffers within the current storage area. The OpenStream method creates such a text buffer and makes it the current output stream. All subsequent writes will go to this stream until it is closed. At which point the current output stream will revert to the file specified in the Output statement.

The following code shows how text buffers as used.

 void DemoWriteTextStreams(string theAuthor)
 {
    int textRoot;
    Handle textStream;

    Write_Line("Write record to Output file before opening a text buffer");
    Write_OpenStream();
    #TextStart
    Hello World
       This is a message from (%= theAuthor %)
    GoodBye World
    #TextEnd
    textRoot = Write_CloseStream();
    Write_Line("Write another record then write content of text buffer");
    textStream = Text_Open(Store_GetHandle(),textRoot);
    Write_TextStream(textStream,0,0);
    Text_Close(textStream);
 }
The records both before and after the write to the text buffer go to the Output file before the buffer itself is written using the Write_TextStream() method. This code then
 <Output Status="New" Filename="Demo003.out" />
 <RunCommand Id="scmCode.DemoWriteTextStreams"  prams="Kilroy"/>
produces the following output.
 Write record to Output file before opening a text buffer
 Write another record then write content of text buffer
 Hello World
    This is a message from Kilroy
 GoodBye World

 Write_Pattern Method

gmSL: void Write_Pattern(string PatString, int nPattern, string Parameters)
gmVB: Sub Write_Pattern(ByVal PatString As String,ByVal nPattern As Integer, ByVal Parameters As String)
gmNI: void Write_Pattern(char* PatString,int nPattern,char* Parameters);

This method enters the pattern string PatString starting at the current location in into the current output record using editing directives within the string along with parameters defined in Parameters. nPattern contains the number of characters in PatString to be used. Parameters contains a semicolon-delimited string containing parameters referenced via their number. If the PatString contains no such references it may be empty. No actual write occurs at this time.

Directives within PatString are enclosed in % signs. The following are recognized:

Directive Meaning
%% Enter a percent sign
%USR_VERSION% Platform specified user version identifier
%PRM_VERSION% Platform specified system version identifier
%PRM_BUILDID% Platform build signature string
%DATE% Current date using currently selected formatting options
%TIME% Current time using currently selected formatting options
%envname% Value of environment variable envname. It must begin with an alphabetic character and may contain no more than 31 characters.
%nd Enter the nth (1-based) parameter string

Note that when called via gmSL if nPattern is set to zero, then the length of PatString will be used.

The following code shows how a pattern can be used.

 void DemoWritePattern(string what, string whom)
 {
    Write_Pattern("The event %1d happened at %TIME% on %DATE% to %2d", 0, what + ";" + Whom);
    Write_Record();
 }
As an example, the following commands
 <Output Status="New" Filename="Demo008.out" />
 <RunCommand Id="scmCode.DemoWritePattern" prams="Got Lost;Kilroy" />
produce the output
 The event Got Lost happened at 13:33:03 on 2013-01-02 to Kilroy
Note that in this case the use of semicolons within the RunCommand prams attribute interferes with the use of semicolons in the Parameters parameter here, so some care must be taken.

 Write_Record Method

gmSL: void Write_Record()
gmVB: Sub Write_Record()
gmNI: void Write_Record(void);

This method completes the authoring of the current output record and then writes the result either to the currently open text buffer or to the file specified in the Output statement. The steps performed before the write include: first, special codes that are used to represent single and double quotes in either escaped or un escaped form must be converted to the final form required by the target language; second, if the echo translation flag is set then the current margin nesting level and the record are written to the log file; third, if the author is writing ASP code then the record must be checked for a transition into or out or VBSCRIPT; and fourth, if the record is longer that the Select MaxOutputWidth value then it is broken into multiple records using the conventions of the target language.

The following code contrasts using Write_Text() and Write_Record() with using Write_Line().

 void DemoWriteRecord(string theAuthor)
 {
    Write_Line("This is a message from " + theAuthor);
    Write_Text("This is a message from ");
    Write_Text(theAuthor);
    Write_Record();
    Write_Text("This is a message from " + theAuthor);
    Write_Record();
 }
Using this, the following commands
 <Output Status="New" Filename="Demo009.out" />
 <RunCommand Id="scmCode.DemoWriteRecord" prams="Kilroy" />
produce this set of identical lines
 This is a message from Kilroy
 This is a message from Kilroy
 This is a message from Kilroy

 Write_Select Method

gmSL: int Write_Select(int unit)
gmVB: Function Write_Select(ByVal unit As Integer) As Integer
gmNI: int Write_Select(int unit);

The Write_Select method selects one the available file structures as the current unit. All successive write support will be performed by this unit until another call to this service is made or until the unit is closed. Note that this service only selects the unit it does not open its output channels or change it in any way. The unit parameter is the unit sequence number of the desired file structure. It must have a value between 1 and 5. Note that unit 1 is connected to the gmPL Output statement and should be used with care. Unit 5 is used by gmBasic as a temporary scratch unit -- not open between tasks -- and should only be used in the same way here.

The following code, reproduced from the discussion of Write_CloseFile() shows how this method can be used to flip back and forth between different files.

 void DemoWriteSelect(string file1,string file2)
 {
    Write_OpenFile(2,file1,True,OutStyle.Text);
    Write_OpenFile(3,file2,True,OutStyle.Text);
    Write_Select(2);
    Write_Line("Line 1 in File " + file1);
    Write_Select(3);
    Write_Line("Line 1 in File " + file2);
    Write_Select(2);
    Write_Line("Line 2 in File " + file1);
    Write_CloseFile();
    Write_Line("Line 1 in Output File");
    Write_Select(3);
    Write_Line("Line 2 in File " + file2);
    Write_CloseFile();
    Write_Line("Line 2 in Output File");
}

 Write_SetIndentation Method

gmSL: void Write_SetIndentation(int indent, int offset)
gmVB: Sub Write_SetIndentation(ByVal indent As Integer, ByVal offset As Integer)
gmNI: void Write_SetIndentation(int indent, int offset);

This method sets the indentation widths for the current output stream. There are two width values: indent which specifies the number of spaces to indent per indentation level (a value of zero means use tabs); and offset which is used when a record is longer than the desired line-width. The following line can be set off this many additional spaces.

When an output file is first created, the default indent value is the Select Indent attribute and the default offset value is zero. When an text buffer is opened the initial values are the values from the current output file. The values specified here take immediate effect and can be changed within the same write sequence.

Consider the following code that writes an un indented line and then an indented one

 void DemoWriteSetIndentation(string comment, int indent)
 {
    Write_SetIndentation(indent,0);
    Write_Line("Unindented Line: " + comment);
    Write_ChangeMargin(1);
    Write_Line("Indented Line: " + comment);
    Write_ChangeMargin(-1);
 }
when called multiple times using various indent values
 <Output Status="New" Filename="Demo010.out" />
 <RunCommand Id="scmCode.DemoWriteSetIndentation" prams="Hello World;8" />
 <RunCommand Id="scmCode.DemoWriteSetIndentation" prams="Hello World;1" />
 <RunCommand Id="scmCode.DemoWriteSetIndentation" prams="Hello World;(%= Select.Indent %)" />
produces the following output
 Unindented Line: Hello World
         Indented Line: Hello World
 Unindented Line: Hello World
  Indented Line: Hello World
 Unindented Line: Hello World
    Indented Line: Hello World
The quantity Select.Indent sets the indentation level back to its original value.

 Write_TableCell Method

gmSL: void Write_TableCell()
gmVB: Sub Write_TableCell()
gmNI: void Write_TableCell(void);

In many complex output situations it is often desirable to nest the output streams so that complex outputs can be nested within each other or can be constructed with independent sets of logic. This method allows for the writing of complex data cells within data tables. Rather than writing the current output record and thus clearing its internal buffers so that another record can be written, this method pushes the content of the current output record onto the runtime data queue and then clears it. Once a series of cells have been written, then the Write_TableRow() method writes a data row to the currently active output stream using the form required by the Output Syntax attribute set for it.

This method writes a table whose data cells contain information about all of the user defined variables in a completed translation.

 Sub DemoWriteTable()
    Dim iRoot As Integer
    Dim levels(19) As Integer

    DataQueue_SetBottom()
    Write_Text "Audit of Variables in " & Store_GetDataName() & " storage area"
    Write_TableCell()
    Write_TableTitle()
    DataQueue_PushString("Lev")
    DataQueue_PushInteger(3)
    DataQueue_PushString("Address")
    DataQueue_PushInteger(8)
    DataQueue_PushString("Full Symbol Identifier")
    DataQueue_PushInteger(-100)
    Write_TableHeadings()

    iRoot = Store_FindFirstChild(levels,0)
    Do while(iRoot <> 0)
       If Store_GetObjectType(iRoot) = ObjectType.VARIABLE Then
          Write_Integer(levels(0) - 1, 0)
          Write_TableCell()
          Write_Integer(iRoot,0)
          Write_TableCell()
          Write_Text(Symbol_FullName(iRoot,-1))
          Write_TableCell()
          Write_TableRow()
       End If
       iRoot = Store_FindNextChild(levels)
    Loop
    Write_TableEnd()
    DataQueue_ClearBottom(1)
 End Sub
A gmPL script that might use this method is as follows
  <gmBasic>
  <Storage Action="Open" Identifier="fmstock1.vbi" />
  <Select GlobalSettings="GmslCode.vbi" />
  <LoadEnvironment />
  <Output Status="New" Filename="Demo011.out" stripTrail="on" />
  <RunCommand Id="vbCode.DemoWriteTable" />
  <Storage Action="Close" />
  </gmBasic>
By convention all of the sample codes are compiled into a global settings file GmslCode.vbi. The class within that file which contains VB code is called vbCode. The fmstock1.vbi file is as it was produced within the FMSTOCK sample code. Nothing special was done to make it usable here. The Open action opens that file with Read Only permission. An abstract of the output follows.
  Audit of Variables in fmstock1.vbi storage area:
  Lev |  Address | Full Symbol Identifier
  --- |  ------- | ----------------------
    4 |   227293 | FMStocks_DB.Helpers.RegisterEventSource.lpUNCServerName
    4 |   227382 | FMStocks_DB.Helpers.RegisterEventSource.lpSourceName
    4 |   232756 | FMStocks_DB.Helpers.DeregisterEventSource.hEventLog
       ...
    3 |   253093 | FMStocks_DB.logDebugMSG.strSource
    3 |   253123 | FMStocks_DB.logDebugMSG.strMSG
    2 |   264958 | FMStocks_DB.COMSVCSLib_AppServer
The actual cells written by the Write_TableCell method are the individual entries in each row of the table.

 Write_TableEnd Method

gmSL: void Write_TableEnd()
gmVB: Sub Write_TableEnd()
gmNI: void Write_TableEnd(void);

This method ends the authoring of a table of values. If the Output Syntax is Html then the Html closing tags are written; else this method does nothing.

Using the DemoWriteTable() subroutine with this script

 <gmBasic>
 <Storage Action="Open" Identifier="fmstock1.vbi" />
 <Select GlobalSettings="GmslCode.vbi" />
 <LoadEnvironment />
 <Output Status="New" Filename="Demo012.html" Syntax="html" />
 <RunCommand Id="vbCode.DemoWriteTable" />
 <Output Status="Close" />
 <Storage Action="Close" />
 </gmBasic>
generates an output table with records like the following
 <html>
   ...
 <center><p><h4>Audit of Variables in fmstock1.vbi storage area</h4></p></center>
 <center><table cellpadding="2" cellspacing="0" bordercolor="#5B5F8B" border="1">
 <tr>
 <th rowspan="1" colspan="1" class="spanner" nowrap="nowrap">Lev</th>
 <th rowspan="1" colspan="1" class="spanner" nowrap="nowrap">Address</th>
 <th rowspan="1" colspan="1" class="spanner" nowrap="nowrap">Full Symbol Identifier</th>
 </tr>
 <tr>
 <td align="right" class="cell-odd" nowrap="nowrap">4</td>
 <td align="right" class="cell-odd" nowrap="nowrap">227293</td>
 <td align="left" class="cell-odd" nowrap="nowrap">FMStocks_DB.Helpers.RegisterEventSource.lpUNCServerName</td>
 </tr>
   ...
 <tr>
 <td align="right" class="cell-odd" nowrap="nowrap">2</td>
 <td align="right" class="cell-odd" nowrap="nowrap">264958</td>
 <td align="left" class="cell-odd" nowrap="nowrap">FMStocks_DB.COMSVCSLib_AppServer</td>
 </tr>
 </table></center>
 </body>
 </html>
In this output the lines at the top before the title and those below the end of the table are produced by the gmPL Output statement. It is the closing table and center entries that are made by the Write_TableEnd() method. When writing code like DemoWriteTable() it is important to remember that its actual output form will be determined at gmPL RunCommand time so always include calls to methods like Write_TableEnd() in case the caller decides to use Html syntax.

 Write_TableHeadings Method

gmSL: void Write_TableHeadings()
gmVB: Sub Write_TableHeadings()
gmNI: void Write_TableHeadings(void);

This method writes a column heading to the currently active output stream using the form required by the Output Syntax attribute set for it. The column headings themselves and their desired widths are stored in the runtime data queue. Reviewing again the DemoWriteTable() subprogram

 Sub DemoWriteTable()
    Dim iRoot As Integer
    Dim levels(19) As Integer

    DataQueue_SetBottom()
    Write_Text "Audit of Variables in " & Store_GetDataName() & " storage area"
    Write_TableCell()
    Write_TableTitle()
    DataQueue_PushString("Lev")
    DataQueue_PushInteger(3)
    DataQueue_PushString("Address")
    DataQueue_PushInteger(8)
    DataQueue_PushString("Full Symbol Identifier")
    DataQueue_PushInteger(-100)
    Write_TableHeadings()

    iRoot = Store_FindFirstChild(levels,0)
    Do while(iRoot <> 0)
       If Store_GetObjectType(iRoot) = ObjectType.VARIABLE Then
          Write_Integer(levels(0) - 1, 0)
          Write_TableCell()
          Write_Integer(iRoot,0)
          Write_TableCell()
          Write_Text(Symbol_FullName(iRoot,-1))
          Write_TableCell()
          Write_TableRow()
       End If
       iRoot = Store_FindNextChild(levels)
    Loop
    Write_TableEnd()
    DataQueue_ClearBottom(1)
 End Sub
It is the DataQueue service class calls that set up the call to Write_TableHeadings which expects the find a series of (String, Integer) pairs in the data queue. The number of pairs defines the number of columns in the table, each string entry defines the column heading, and the integer entry defines the field width and orientation to the used as follows:

Value Meaning
+n Right justify the characters in a cell n characters wide.
-n Left justify the characters in a cell n characters wide.

These values are actually only used when the Output Syntax is Text; however, since this syntax choice does not take effect until gmPL runtime, the values should always be supplied with reasonable values.

 Write_TableRow Method

gmSL: void Write_TableRow()
gmVB: Sub Write_TableRow()
gmNI: void Write_TableRow(void);

This method writes a data row to the currently active output stream using the form required by the Output Syntax attribute set for it. The cell content making up the data row are stored as strings on the runtime data queue. Reviewing again the DemoWriteTable() subprogram

 Sub DemoWriteTable()
    Dim iRoot As Integer
    Dim levels(19) As Integer

    DataQueue_SetBottom()
    Write_Text "Audit of Variables in " & Store_GetDataName() & " storage area"
    Write_TableCell()
    Write_TableTitle()
    DataQueue_PushString("Lev")
    DataQueue_PushInteger(3)
    DataQueue_PushString("Address")
    DataQueue_PushInteger(8)
    DataQueue_PushString("Full Symbol Identifier")
    DataQueue_PushInteger(-100)
    Write_TableHeadings()

    iRoot = Store_FindFirstChild(levels,0)
    Do while(iRoot <> 0)
       If Store_GetObjectType(iRoot) = ObjectType.VARIABLE Then
          Write_Integer(levels(0) - 1, 0)
          Write_TableCell()
          Write_Integer(iRoot,0)
          Write_TableCell()
          Write_Text(Symbol_FullName(iRoot,-1))
          Write_TableCell()
          Write_TableRow()
       End If
       iRoot = Store_FindNextChild(levels)
    Loop
    Write_TableEnd()
    DataQueue_ClearBottom(1)
 End Sub
The individual calls to Write_TableRow() assume that they have been preceded by as many calls to Write_DataCell() as there were columns defined in the table via the DataQueue calls and the final call to Write_TableHeadings(). The actual output produced by this method is determined at gmPL runtime depending upon the setting of the Output Syntax attribute. Previous topics have shown the output for Text (see Write_TableCell()) and Html (see Write_TableEnd()). The script here uses Tabbed syntax.
 <gmBasic>
 <Storage Action="Open" Identifier="fmstock1.vbi" />
 <Select GlobalSettings="GmslCode.vbi" />
 <LoadEnvironment />
 <Output Status="New" Filename="Demo013.out" Syntax="Tabbed" />
 <RunCommand Id="vbCode.DemoWriteTable" />
 <Output Status="Close" />
 <Storage Action="Close" />
 </gmBasic>
The following is an abstract of the output produced, note that the white space is produced by the tabs.
 Audit of Variables in fmstock1.vbi storage area
 Lev	Address	Full Symbol Identifier
 4	227293	FMStocks_DB.Helpers.RegisterEventSource.lpUNCServerName
 4	227382	FMStocks_DB.Helpers.RegisterEventSource.lpSourceName
 4	232756	FMStocks_DB.Helpers.DeregisterEventSource.hEventLog
       ...
 3	253093	FMStocks_DB.logDebugMSG.strSource
 3	253123	FMStocks_DB.logDebugMSG.strMSG
 2	264958	FMStocks_DB.COMSVCSLib_AppServer
Regardless of the output syntax used, it is implemented at runtime when the various Write_Table methods are used. It is important to remember this when writing code that uses them.

 Write_TableTitle Method

gmSL: void Write_TableTitle()
gmVB: Sub Write_TableTitle()
gmNI: void Write_TableTitle(void);

This method writes a title for a table of values along with any other control information that may be needed to begin the actual table display to the currently active output stream using the form required by the Output Syntax attribute set for it. The title itself is stored on the runtime data queue prior to the call to this method. The easiest way to do this is via the Write_TableCell() method though the DataQueue_PushString() could be used as well. Reviewing again the DemoWriteTable() subprogram,

 Sub DemoWriteTable()
    Dim iRoot As Integer
    Dim levels(19) As Integer

    DataQueue_SetBottom()
    Write_Text "Audit of Variables in " & Store_GetDataName() & " storage area"
    Write_TableCell()
    Write_TableTitle()
       ....
the actual form of the output depends upon the Output Syntax attribute. For Text a colon is added to the back of the title string.
 Audit of Variables in fmstock1.vbi storage area:
For tabbed the title string is unadorned.
 Audit of Variables in fmstock1.vbi storage area
For Html it is displayed as an h4 centered heading.
 <center><p><h4>Audit of Variables in fmstock1.vbi storage area</h4></p></center>

 Write_Text Method

gmSL: void Write_Text(string strValue)
gmVB: Sub Write_Text(ByVal strValue As String)
gmNI: void Write_Text(char* strValue);

This method appends all characters from strValue to the current output record. No actual write occurs at this time. No formatting is applied to the string; however, the engine supporting gmSL performs concatenation and automatic conversions to string when processing addition within contexts that expect string arguments. For example the following code uses Write_Text

 void DemoWriteText(int opcValue)
 {
    tOpcInfo opcInfo;

    opcInfo = Opcode_GetInfo(opcValue);
    Write_Text("The Opcode " + opcInfo.ident + " has value " + opcInfo.value);
    Write_Record();
    Write_Text("   length    = " + opcInfo.length);
    Write_Record();
    Write_Text("   ident     = " + opcInfo.ident);
    Write_Record();
    Write_Text("   value     = " + opcInfo.value);
    Write_Record();
    Write_Text("   type      = " + Symbol_NamedEntryLabel("opcTypes",opcInfo.type));
    Write_Record();
    Write_Text("   role      = " + Symbol_NamedEntryLabel("opcRoles",opcInfo.role));
    Write_Record();
 }
to describe operation code properties. When called as follows
 <Output Status="New" Filename="Demo014.out" />
 <RunCommand Id="scmCode.DemoWriteText"  prams="5"/>
 <RunCommand Id="scmCode.DemoWriteText"  prams="13"/>
 <RunCommand Id="scmCode.DemoWriteText"  prams="170"/>
the following output is produced.
 The Opcode LIC has value 5
    length    = 17
    ident     = LIC
    value     = 5
    type      = ShortValue
    role      = LoadInt
 The Opcode ADD has value 13
    length    = 17
    ident     = ADD
    value     = 13
    type      = Arithmetic
    role      = Binary
 The Opcode USC has value 170
    length    = 17
    ident     = USC
    value     = 170
    type      = DoubleByte
    role      = Clsref

 Write_TextStream Method

gmSL: void Write_TextStream(Handle textStream, int host, int margin)
gmVB: Sub Write_TextStream(ByVal textStream As Handle, ByVal host As Integer, ByVal margin As Integer)
gmNI: void Write_TextStream(void* textStream,int host, int margin)

This method writes the content of a text stream buffer to the current output file. The textStream parameter is obtained from one of the Text service class methods Text_Open() or Text_Create(). It is the handle to the text stream buffer to be written. The host parameter is the root offset of the symbol to which the text stream belongs. It may simply be zero. If nonzero, it is used to log this message

 SYSERR#6067: Text storage malformed for <identifier of symbol>
in case the text stream is malformed. The margin parameter is the starting indentation margin to be used while writing the text stream. When gmBasic writes text streams it does not insert any leading white space to show marginal indentation; rather it simply records the margin level for each line. It is when the text stream is actually written that the margin level times the indentation width white space is actually applied to the front of the record. When doing this, the value of margin is added to the margin value recorded for each line.

The following method shows how the translation associated with a class file can be authored.

 void DemoAuthorTextStream(int classRoot)
 {
    tInfoFile classFile;
    Handle    textStream;

    classFile = Store_GetVector(classRoot);
    textStream = Text_Open(Store_GetHandle(),classFile.tranBase);
    Write_TextStream(textStream,classRoot,0);
    Text_Close(textStream);
 }
In the following script
 <gmBasic>
 <Storage Action="Open" Identifier="fmstock1.vbi" />
 <Select GlobalSettings="GmslCode.vbi" />
 <LoadEnvironment />
 <Output Status="New" Filename="Demo015.out" />
 <RunCommand Id="vbCode.DemoAuthorTextStream"
    prams="(%= Symbol_FindIdentifier("[C:\gmSrc\fmstocks\vb6\FMStocks_DB\Version.cls]",0) %)" />
 <Storage Action="Close" />
 </gmBasic>
the gmPL preprocessor executes the Symbol_FindIdentifier method which returns the root offset of the specified symbol and inserts it in string form in the prams attribute. The RunCommand then passes that root offset as an integer value to the DemoAuthorTextStream() method. That method then writes the translation associated with the class just as it was produced when the actual translation script was executed. Here is an abstract of that output
 cat >C:\gmProj\FmStocks\Deploy\FmStock1_csh\Version.cs <<'!)(!'
 using System;
 using System.Drawing;
   ...
 namespace FMStocks_DB
 {
    public class Version
    {
       private const string m_modName = "FMStocks_DB.Version";
       public string ConnectionString()
       {
          string ConnectionString = "";

          DBHelper dbh = null;
          try
          {
             MigrationSupport.Lib.ClearErrorObject();
             dbh = new FMStocks_DB.DBHelper();
             ConnectionString = dbh.GetConnectionString();
             dbh = null;
             return ConnectionString;

          }
          catch(Exception exc)
          {
             MigrationSupport.Lib.SetErrorObject(exc);
             Helpers.RaiseError(m_modName,"ConnectionString()","",0,false);
          }
          return ConnectionString;
       }
    ...
 }
 !)(!