Registry is either a terminal or nonterminal command statement that occurs in both command and reference scripts. The registry is a directory which stores named settings and options for a variety of special uses within gmBasic or within user specified runtime Dlls. It contains a simple hierarchical set of name-value pairs stored under a type identifier. The values are either simple strings or a text buffer.
The attributes of the Registry statement are as follows:
|Type||This attribute contains the identifier of the "special use" of the name-value pair being entered. If it is omitted, then the value LibName is supplied. Though gmBasic, itself uses a set of these types which are reserved, any other identifiers may be used. They are simple identifiers beginning with a letter and containing only letters and numbers. They are not case-sensitive.|
|Source||This attribute contains the source name of the pair to which a target value is to be assigned. It may have any content. If a given pair is intended to be unique within a given type, then its name must be unique within that type only. They are not case-sensitive and may contain special characters like periods.|
|Target||This attribute is used only with the terminal form of the statement. It contains the target value of the pair. It may have any content and need not be unique. At any given time a given source with a given type can have only one target. If the target attribute is missing or empty then the name value pair is treated as though it no longer exists within its location.|
For the nonterminal form of the Registry statement the records in the scope of the statement are entered into a text buffer in raw form and that buffer is then associated with the source name. Any gmSL processing which these raw statements might undergo is performed when they are used not here where they are simply stored.
The current, globalsettings, and language storage areas all contain registries. Which registry is searched for a given type depends upon the type. They are as follows.
Dependency is a terminal registry type that is stored in the current storage area. Many ASP sites suffer from what is called "Omitted Include Syndrome". That is they contain code that depends on other includes, but not all of these needed includes are in the scope of every pageslice. This is particularly troublesome when the omitted includes contain variable declarations or scripted classes. The registry Dependency type is used to deal with this syndrome.
The attributes of the Dependency type are as follows:
|Source||Pathname of include with a dependency|
|Target||Pathname of include depended upon|
The tool processes this registry type as follows:
Since the algorithm does not require that dependent includes precede their sources, it is not expected to cycle. However, sites with cyclic include references do exist which may well be complicated by the aggressive use of this facility -- so user beware.
EditFile is a nonterminal registry type that is stored in the globalsettings storage area. Very large code sites consisting of many, often shared, code files that require fixes need a way to organize these fixes. The simple use of general script templates to apply to all jobs in a migration set requires that each command script processed by gmBasic include all fixes for all jobs. In these template script files Fix statements are skipped if their host is not defined in the job at hand. In processing these, the search for the host has to be performed and the actual statements being skipped have to be checked for the termination record. These are trivial operations for small sites, but can quickly build up for large sites.
The EditFile source attribute specifies the full pathname of the file to be edited. The actual Fix statements then form the target text buffer.
When a source file is initially loaded, be it a code file, or a VBP project file, or a web file, the globalsettings registry is checked for an EditFile on its full pathname. If present, the fixes are applied to the file using the standard facilities of the Fix statement.
The other advantage of using EditFile as opposed to the Compile Fix statement is that it is file specific not compilation set specific. Compile fix, for example, cannot edit the project file directly in its raw form as EditFile can. In the case of web files they are first converted into compilable form before they are presented to the compiler for processing. This form is close to the form of the raw web page, but it is sometimes difficult to construct the fix specifications correctly. EditFile simply sees the web file when it is loaded before any other processing occurs.
FixType is a terminal registry type that is stored in the current storage area. It is used to fix the types of source code symbols when they are first encountered. gmBasic uses FixType registry statements when it authors the TypeInference reference script; however, they can also easily be entered into command scripts or be authored via gmNI.
The attributes of the FixType type are as follows:
|Source||The possibly qualified identifier of a source code symbol whose type is the be fixed. Each time a new symbol reference is encountered gmBasic forms its fully qualified identifier, namespace.class.member.[..]. This identifier is then checked for a FixType target. If not found, the namespace component is removed from the fully qualified identifier, and that is checked for a target, and so on. Thus, depending upon how this attribute is written it can fix the type of only one symbol or of many symbols that have the same name.|
|Target||The type to be applied to symbols whose identifiers match the source. This is either an identifier of one of the built in types or it is the qualified identifier of a user or external type.|
The checks for the FixType registry entries are made during pass1 of the compiler when it encounters the definition of a variable or subprogram that is specified as VARIANT or OBJECT. They are also made by the pass2 compiler when it encounters the reference to an undeclared variable,
FixStatus is a terminal registry type that is stored in the current storage area. It is used to change the translation status of a web page to UserControl as opposed to a code class or a regular aspx page.
The attributes of the FixStatus type are as follows:
|Source||The full pathname of the asp page whose status is to change.|
|Target||An identifier for the status desired. At this time the only entry is UserControl which means to translate the page as a usercontrol.|
The FixStatus entries are checked for at compile time, so they must precede the first compile statement that will load the file.
Guid is a terminal registry type that is stored either in the current storage area or the language storage area. The user storage area is checked first. Entries of this type are checked for by the gmSL.Runtime.Guid() method, which has one string parameter GuidName. That method attempts to find a Guid type entry whose source matches its parameter. If found, the target value is the guid to be used. If not found a new guid is generated and used.
The attributes of the Guid type are as follows:
|Source||The logical name of the guid being sought. At the present time authoring methods within gmBasic seek the following logical names: Project, ProjectType1, ProjectType2, Flavor, and Interfaces. All have default values registered in the language file. Users can add additional logical names as needed.|
|Target||The actual GUID to be used for the logical name.|
The default values for the logical names currently being used are
To change them, simply add an equivalent statement to the command script that does the authoring. Such entries are often put in the environment files loaded by scripts.
IdfStatus is a terminal registry type that is stored in the current storage area. Reference scripts describing an external component like a Dll, or an ocx, or an olb, or a tlb are referred to as IDFs -- "Interface Description Files". The IdfStatus specifies how references to these components are to be treated. There four possible target settings -- Build, Migrate, Interop and External. When the Buildfile Select is local or global then the default IdfStatus is Build and the tool will author external dependencies as stub files or stub projects respectively. When BuildFile is off then the default IdfStatus is Migrate and the tool will author external dependencies as an assembly reference. The Interop setting is an intermediate one which says that any Mig files associated with the reference should be ignored. The External status blocks the authoring of stubs completely.
This attribute overrides the default status of the reference. The attributes of the IdfStatus type are as follows:
|Source||The identifier of the external component whose default status is to be overridden.|
|Target||One of the status identifiers: Build, Migrate, Interop or External.|
MigrationSupport has special status in the system. The registry entry
or adding the attribute idfStatus="external" to the library command causes MigrationSupport.dll to behave as other libraries do.
Include is a terminal registry type is stored in the current storage area. When gmBasic loads include files from ASP pages it first forms the full name of the include based on the pathname of the including file. Once this has been formed, the registry is checked for an Include entry that can specify a different pathname.
The attributes of the Include type are as follows:
|Source||The pathname of the include as it would be formed by combining it with the pathname of the including file.|
|Target||The actual pathname to be used for the include.|
LibName is a terminal registry type that is stored in the current storage area. It is used to change the name of an external component from the way it is being referenced either in the project file or in the source code into the name of the component describing it in the migration. External libraries are ultimately identified via their filename like mso.dll or msword9.olb or mscomctl.ocx or msado20.tlb. There are, however, in the windows registries at the home sites often alternative ProgIds registered for these names. It is these ProgIds that are used in the codes. The first reason for using the this registry type is to reconvert the ProgIds back into the local filenames.
The second reason for using the LibName registry type is to supply the name of a migrated description of the component to the translation scripts. Thus, if mscomctl.ocx has a migrated description in a file GM.mscomctl.ocx, then this type is used to make the switch.
The third reason is that source code bases often reference different versions of what is logically the same external component. For example there might be references to both msado25.tlb and msado21.tlb. In the translations the two get mixed and as such their classes are viewed as being different. Also redundant migration instructions need to be constructed. A set of statements like
resolves these problems.
The attributes of the Libname type are as follows:
|Source||The pathname or ProgId of the external as it appears in the source code or project file.|
|Target||The actual library local filename to be used to load the reference script that describes the external.|
MigFile is a terminal registry type that is stored in the current storage area. It is used to specify the name of a Migration File to be associated with an Interface Description File (IDF). This allows more descriptive Migration Filenames to be used as is making it easier to work with different version of Migration Files and so more details arereported in the translation log.
For example, suppose you have three different Migration files for excel.exe, each one specifying a different strategy for upgrading references to the Excel API:
|mig.Excel_StrongTypeStub.xml||A RefactorLibrary containing rules that improve type inference of excel references|
|mig.Excel_MSInterop.xml||A RefactorLibrary containing rules that migrate to use the Primary Interop Assembly for excel|
|mig.Excel_Aspose.xml||A RefactorLibrary containing rules that migrate to use the Aspose Cells API|
Then the different commands could be used to load one of the Migration Files. Generally only one would be used at a time:
The attributes of the MigFile type are as follows:
|Source||The name of the IDF (note the XML extension is not specified)|
|Target||The name of the Migration File to associate with the source IDF (note this form does not include the file extension, .xml is assumed). Alternatively, Target may be the path of the file to be loaded in either absolute form or relative to the working directory (generally the workspace\log folder).|
The tool looks for the target Migration File using the standard metalanguage search process: looking in the target, local, system and language locations in that order.
Note: The Migration File name mig.file.ext.xml is automatically associated with the IDF named file.ext.xml so a registry command is not needed for that case.
ProgId is a terminal registry type that is stored in the current storage area. It is used in two different contexts to change site specific application.class names into fully qualified external class names. The attributes of the ProgId registry type are as follows:
|Source||The identifier of the ProgId as determined from the call. The details of this determination are described below.|
|Target||The identifier to be substituted for the ProgId to resolve its reference.|
The first context is to resolve the ProgId argument value passed to the VB6/ASP CreateObject methods. There are two ways to invoke a component within the VB6-ASP environment: Server.CreateObject and CreateObject.
The original VB6 CreateObject method creates and returns a reference to an ActiveX object. The ProgId argument contains the application name and class name of the object to create. The optional servername contains the name of the network where the object will be created. So far in this development effort this second argument is ignored. The Server.CreateObject method has the same first ProgId argument but does not have the second optional servername argument. Since this one is ignored anyway, we can treat the two in the same way.
The ProgId argument uses the syntax appname.objecttype and has these parts:
|appname||is the name of the application. In so as this implementation is concerned it is the name member of a currently loaded library or is the name of a current project within a multi-project script.|
|objecttype||is the name of the CLASS or INTERFACE that specifies the object type to be created.|
The runtime difference between the two is that Server.CreateObject invokes Microsoft Transaction Server (MTS) to create the object and handle it, whereas CreateObject goes straight to it.
In the migrated code this decision would be made at a component or application level, rather than depending upon the decision made by the original programmer, so here the two are treated in the same way as follows:
Here are some examples
The second context is in ASP OBJECT statement references. In this case the object defined in the ID attribute is declared with the class type of the PROGID attribute. The tool scans the ProgId entries in the registry for any substitutions before it attempts to resolve the actual class reference. Here is an example
RefactorFile is a nonterminal registry type that is stored in the globalsettings storage area. Very large code sites consisting of many, often shared, code files whose symbols require refactoring organize these statements. The simple use of general script templates to apply to all jobs in a migration set requires that each command script processed by gmBasic check all refactoring statements for all jobs. In processing these, the symbol search has to be performed for each. This is a trivial operation for small sites, but can quickly build up for large sites.
The RefactorFile source attribute specifies the full pathname of the file whose symbols are to be refactored. The actual Refactor statements then form the target text buffer.
The registry is checked once for a RefactorFile entry for each class, module, form, or ASP file after the symbols for that file have been loaded but before and code has been compiled. There is nothing special about the refactor statements themselves. They behave exactly the same as Refactor statements placed within a Compile statement for a code project containing the specified file. Thus, the entry
in a selected global settings file is identical to the following in a translation script
Note the need in the FileFilter attribute for the square brackets surrounding the filename. They are supplied for the registry filename which must not contain those the brackets.
SharedFile is a terminal registry type that is stored in the globalsettings storage area. The statements themselves are authored by the SharedFile utility statement. It is used to identify those files that are used by more than one VB6 project and to identify which project should be the only one that processes it. The other projects then refer to the components in the shared file as though they were external library components.
The attributes of the SharedFile type are as follows:
|Source||The full pathname of a code file that is shared by multiple code project.|
|Target||The full pathname of a project file that is to be defining project for the shared file.|
The SharedFile statement description contains a detailed discussion.
UsesInterfaces is a terminal registry type is stored in the globalsettings storage area. It is used to resolve references between independent projects that do not correspond to the build order -- i.e., a reference by a project early in the build order to one later in the order. These can even become circular references. A circular reference occurs when two projects reference each other either directly or indirectly via intermediate references. Clearly no rearrangement of the build order can be made to resolve circular references. To make this workable under .NET a migration is needed that uses interfaces to describe those classes that are being referenced before they are defined. Codes that use these interfaces must now reference the interface classes and not the concrete classes; and codes that define classes that are to be used in interface form must define those interfaces.
For example, assume a small system consisting of two projects Project1 and Project2 is built in that order. The problem is that Project1 references a class2 in Project2 and Project2 references a class1 in Project1. To resolve this, gmBasic creates an interface for class2 that defines the public methods of that class in project2 and any references to class2 in Project1 are changed into references to the interface class as opposed to the concrete class. Now when gmBasic processes Project2 it makes certain that Project2 implements the interface class in the concrete code for that class.
The first problem is to determine what information is needed to perform the uses interfaces migration and how that information can be specified. The information needed is a list of projects that must use interfaces along with a list of which projects supply those interfaces. In the example described above then the list would be
Note that the list is in build order since some of the low level symbol referencing migrations are dependent on this order. The UsesInterfaces registry type is used to store the list.
The attributes of the UsesInterfaces type are as follows:
|Source||This attribute contains the Exename32 name of the using project.|
|Target||This attribute contains a comma-delimited list of the Exename32 names of the supplying projects.|
The symbol table retains the order in which the registry commands are entered under a given type, so determining order of entry is simple. In the present case then the registry statements would be as follows.
If a given project must reference more that one other project via an interface, then the target entry may contain a comma-delimited list. This might look as follows.
The Exename32 attributes are used to reference projects, not their filenames. This is because within referencing projects the library name is needed. It is the Exename32 attribute that supplies this name. Though the worse case scenario is a circular reference, the approach here does not assume this. Rather as each project code is processed, if its Exename32 is one of the target UsesInterfaces entries then all global classes in that project are classified as supplying an interface and all classes referenced in library files whose library name is one of the source are classified as using an interface.
At this point in time the UsesInterfaces list must be constructed by hand. The BuildOrder report does detect ordering problems but that detection does not appear to have enough information at this time. The basic rule is that if a project references a class from an earlier project either as the type of a method or as the type of a parameter to a method or as an instantiation within a method, then an interface must be used.