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 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.
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 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 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 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 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 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 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.
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 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 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 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 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 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 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 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.
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.
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.
|
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.
|
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.
|
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
|
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
|
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 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 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 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 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 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 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 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 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 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 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 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
|
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 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 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 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 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 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.
|
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:
- Renaming symbols either to avoid clashes or to make them easier to maintain.
- Reauthoring a subprogram because its original approach is inappropriate or
unworkable in the .NET environment
- Changing the type of a symbol which was either undefined or too weakly
specified.
- Changing the status of a symbol to change its scope or behavior
- Changing the structure of a symbol to clarify its size and dimensionality.
- Removing a symbol because it is not needed or wanted.
- Changing logic flow and/or program operations to conform to new requirements.
- 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:
- Loading the VB6/ASP source code.
- Fixing the VB6/ASP source code.
- Building the symbol table from the source code
- Compiling the source code into intermediate code
- Analysing the symbol table and intermediate code
- Authoring the target code from the intermediate code and symbol table
- Fixing the target code
- 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.
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 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 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.
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 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 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 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 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 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 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 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 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 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 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.
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 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 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 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 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 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 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 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 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.
|
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.
|
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 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 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 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 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 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
|
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.
|
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.
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
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.
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.
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.
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.
The Symbol class is the root class for all symbols stored in a virtual binary information
file.
Synopsis:
<Property id="Ident" type="String" status="ByVal" opcode="SYM.Ident" />
Synopsis:
<Property id="Name" type="String" status="ByVal" opcode="SYM.Name" />
Synopsis:
<Property id="ObjectType" type="gmsl.ObjectType" status="ByVal" opcode="SYM.ObjectType" />
Synopsis:
<Property id="Parent" type="Symbol" status="ByVal" opcode="SYM.Parent" />
Synopsis:
<Property id="Tree" type="Collection" status="ByVal" opcode="SYM.Tree" />
Synopsis:
<Property id="Children" type="Collection" status="ByVal" opcode="SYM.Children" />
Synopsis:
<Property id="Level" type="Integer" status="ByVal" opcode="SYM.Level" />
Synopsis:
<Property id="FullName" type="String" status="ByVal" opcode="SYM.FullName" />
Synopsis:
<Method id="DisplayObjectType" type="void" nPram="0" opcode="SYM.DispObjectType"/>
Synopsis:
<Method id="WriteNamedFlags" type="void" nPram="1" opcode="SYM.WriteNamedFlags" >
<Argument id="flags" type="Integer" status="ByVal"/>
</Method>
Synopsis:
<Method id="WriteSurfacePattern" type="void" nPram="1" opcode="SYM.WriteSurfacePattern" >
<Argument id="pattern" type="Integer" status="ByVal"/>
</Method>
The MigInfo class encompasses all symbols that can be migrated in a virtual binary information file.
Its parent is the Symbol class.
Synopsis:
<Attribute id="migPattern" type="Integer" />
Synopsis:
<Attribute id="migFlags" type="MigProcessFlags[]" />
Synopsis:
<Attribute id="migStatus" type="MigStatusFlags[]" />
Synopsis:
<Attribute id="migComment" type="String" />
Synopsis:
<Attribute id="migTransform" type="Integer" />
Synopsis:
<Attribute id="migRuntime" type="Integer" />
Synopsis:
<Attribute id="context" type="contextFlags[]" />
Synopsis:
<Attribute id="aspContext" type="AspContextFlags[]" location="context" />
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.
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.
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.
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.
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.
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.
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.
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.
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.
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.
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.
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.
Synopsis:
There is no return value.
Synopsis:
There is no return value.
Synopsis:
There is no return value.
Synopsis:
There is no return value.
Synopsis:
There is no return value.
Synopsis:
There is no return value.
Synopsis:
There is no return value.
Synopsis:
There is no return value.
Synopsis:
There is no return value.
Synopsis:
There is no return value.
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:
- The cat statement for the Design partial class.
- The namespace (note the wizard has no namespace)
- 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.
- 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:
- The cat statement needed by the deployment tool
- Any imports or usings that may be needed
- The namespace and class declarations
- 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 T | he 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.
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.
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 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.
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>
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 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 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 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 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
|
The Author service class contains component authoring utilities.
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
Author_ExternalStubs
Author_GetTypeString
Author_InitValue
Author_Interface
Author_InterfaceEntry
Author_Pattern
Author_ProjectCompileIncludes
Author_ProjectExternals
Author_SetVbName
Author_SupportReference
Author_Type
The Compile servive class gives access to the compiler passes.
Compile_Pass1
Compile_Pass2
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 class does standard list processing
List_AddEntry
List_FindByName
The Meta service class works with Meta language information
Meta_LoadObjectModel
Meta_RunMethod
Meta_UseTemplate
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
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 class accesses the registry.
Registry_GetNameValue
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:
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 obtains the current set of selected attribute values
Select_GetFlags
The Source tokens the current source input text buffer
Source_Insymbol
Source_LookAhead
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 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 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 class accesses files in the system
System_MakeFileName
System_ParseFileName
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 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;
}
...
}
!)(!