[an error occurred while processing this directive]

HP OpenVMS Systems

BASIC Translator
Content starts here

Compaq BASIC Translator
User Manual


Previous Contents Index


Chapter 4
Data Definition and Representation

This chapter briefly describes data type definition and data representation as these topics relate to the Translator. Refer to the appropriate VAX BASIC, DEC BASIC, or Visual Basic documentation for more information on data types.

4.1 Data Types

Table 4-1 lists the VAX BASIC or DEC BASIC keywords used to assign data types along with their size and range.

Table 4-1 VAX BASIC or DEC BASIC Data Types
Data Type Keyword Size Range
BYTE 1 byte --128 to +127
WORD 2 bytes --32768 to +32767
LONG 4 bytes --2147483648 to +2147483647
SINGLE 4 bytes +/-- .29E--38 to 1.7E38
DOUBLE 8 bytes +/-- .29E--38 to 1.7E38
GFLOAT 8 bytes +/-- .56E--308 to .90E308
DECIMAL(d,s) 0 to 16 bytes +/-- 1E--31 to 1E31
STRING One character per byte 1 to 65535 (string range)
0 to 255 (single character range)
RFA 6 bytes NA

Table 4-2 lists the supported Visual Basic data types and their size and range.

Table 4-2 Visual Basic Data Types
Data Type Keyword Size Range
Byte 1 byte 0 to 255
Boolean 2 bytes True or False
Integer 2 bytes --32768 to +32767
Long 4 bytes --2147483648 to +2147483647
Single 4 bytes +/-- 1.4E--45 to 3.4E38
Double 8 bytes +/-- 4.9E--324 to 1.8E308
Currency 8 bytes --922,337,203,685,477.5808
to 922,337,203,685,477.5807
Date 8 bytes January 1, 100 to December 31, 9999
Object 4 bytes Any Object reference
String (variable-length) 10 bytes + string length 0 to approximately 2 billion (approximately 65,400 for Microsoft Windows Version 3.1 and earlier)
String (fixed-length) Length of string 1 to approximately 65,400
Variant (with numbers) 16 bytes Any numeric value up to the range of a Double
Variant (with characters) 22 bytes + string length Same range as for variable-length String
User-Defined (using Type) Number required by elements The range of each element is the same as the range of its data type

4.2 Data Representation

One of the major areas of concern in a migration effort has to do with the differences in data representation between the source and destination platforms. These concerns do not have as much to do with the actual memory layout as they do with the range and precision of the equivalent data types. Most of these differences come from the platform itself, not the language being used. The Translator converts each VAX BASIC or DEC BASIC data type to the closest reasonable Visual Basic data type.

This section lists differences between the VAX BASIC or DEC BASIC data types and the Visual Basic data types.

4.2.1 Integer Data Type

The integer data types are 1, 2, or 4 bytes long. The following sections compare them for each integer size.

Byte Data Type (1-Byte Integer)

The VAX BASIC or DEC BASIC BYTE data type is translated to the Visual Basic Byte data type with a difference in range. Although both are 1-byte integers, the VAX BASIC or DEC BASIC BYTE is signed, giving it a range of -128 to 127. The Visual Basic Byte is unsigned, giving it the range of 0 to 255. The Translator gives a warning during the translation of a BYTE declaration. It also flags the use of this data type within EXTERNAL statements.

Word Data Type (2_Byte Integer)

The VAX BASIC or DEC BASIC WORD data type is translated to the Visual Basic Integer data type with no differences in the number that they can contain. Each one is a signed 2-byte integer capable of holding a value from --32768 to +32767.

Longword Data Type (4-Byte Integer)

The VAX BASIC or DEC BASIC LONG data type is translated to a Visual Basic Long data type with no differences in the number that they can contain. Each one is a signed 4-byte integer capable of holding a value from --2147483648 to +2147483647.

4.2.2 Floating-Point Data Type

Floating-point is the most system-dependent data type. The single and double floating-point representations within Visual Basic follow the IEEE standard. However, VAX BASIC and DEC BASIC both use VAX floating-point representations. The differences are discussed below.

Single Data Type

The VAX BASIC or DEC BASIC SINGLE data type is translated to the Visual Basic Single data type. The VAX BASIC or DEC BASIC SINGLE (also known as FFLOAT) is a 4-byte representation that can contain the following:

+/-- .29E--38 to 1.7E38, with 6 digits of precision

The Visual Basic Single (IEEE) representation is also 4 bytes, but can contain the following:

+/-- 1.4E--45 to 3.4E38, with 6 digits of precision

Double Data Type

The VAX BASIC or DEC BASIC DOUBLE data type is translated to the Visual Basic Double floating-point data type. The VAX BASIC or DEC BASIC DOUBLE (also known as DFLOAT) is an 8-byte data representation that can contain the following:

+/-- .29E--38 to 1.7E38, with 16 digits of precision

The Visual Basic Double (IEEE) representation is also 8 bytes, but can contain the following:

+/-- 4.9E--324 to 1.8E308, with 15 digits of precision

Although the DFLOAT representation can contain 16 digits of precision, the Alpha platform cannot perform operations on this format in native mode. Therefore, in DEC BASIC, the number is first converted to GFLOAT before any operations take place. Because of this conversion, the number loses the 16th digit of precision whenever an operation is performed on it.

Gfloat Data Type

The VAX BASIC or DEC BASIC GFLOAT data type is translated to the Visual Basic Double floating-point data type. The VAX BASIC or DEC BASIC GFLOAT is an 8-byte data representation that can contain the following:

+/-- .56E--308 to .90E308, with 15 digits of precision

The Visual Basic Double (IEEE) representation is also 8 bytes, but can contain the following:

+/-- 4.9E--324 to 1.8E308, with 15 digits of precision

4.2.3 String Data Type

One difference should be noted between all strings within VAX BASIC or DEC BASIC and all strings within Visual Basic. VAX BASIC and DEC BASIC use the ANSI standard internally to represent strings, while Visual Basic uses UNICODE internally to represent strings. UNICODE is a 2-byte per character representation most often used for internationalization. Although Visual Basic uses UNICODE internally, all strings enter and leave Visual Basic as ANSI strings. Visual Basic reads ANSI standard strings from files and writes ANSI standard strings to files. When Visual Basic passes strings to an external routine, it first generates a temporary ANSI representation of the strings and passes them instead.

The two variations of the STRING data type are discussed below.

Dynamic String Data Type

The VAX BASIC or DEC BASIC dynamic STRING data type is translated to the Visual Basic variable-length String data type. In both VAX BASIC or DEC BASIC and Visual Basic, dynamic strings are managed using a descriptor block that points to the actual string. The dynamic string data type can dynamically change its size to hold whatever string is being assigned to it by deallocating and reallocating memory.

Static String Data Type

The VAX BASIC or DEC BASIC static STRING data type is translated to the Visual Basic fixed-length String data type. Internally, Visual Basic static strings take up 2 bytes per character, impacting the real size of an in-memory user-defined record. However, when the record is read or written, the string is converted from or to ANSI, making the size of the record in the file the size expected. If you need to maintain a 1-byte per character in-memory allocation, you can use a byte array to accomplish this. Visual Basic has versions of the string handling functions that work with byte arrays as if they were strings. Refer to the Visual Basic documentation for more information.

4.2.4 Decimal Data Type

Visual Basic Version 5.0 and 6.0

Currently there is only limited support for the Decimal data type in Visual Basic. Refer to the Visual Basic Version 5.0 or 6.0 documentation for more information.

In Visual Basic Version 5.0 and 6.0, the Decimal subtype of the Variant type is similar to the VAX BASIC or DEC BASIC DECIMAL type. See Chapter 7 for detailed information.

Note

The VAX BASIC or DEC BASIC DECIMAL data type can be up to 16 bytes long, and contain up to 31 digits of precision with a scale factor of 0 to 31. It is highly recommended that you review each use of a translated DECIMAL data type and try to find a more appropriate data type to match your needs. For example, the size and layout of a record that contains a DECIMAL data type will be different in the translated code. Other possible Visual Basic matches include the Visual Basic Currency data type, which has a precision of 19 digits and a fixed scale factor of 4.

Visual Basic Version 4.0

The VAX BASIC or DEC BASIC DECIMAL data type has no corresponding data type in Visual Basic Version 4.0. Visual Basic Version 4.0 will flag the CDec function, which the Translator uses to perform the conversion, as an error.

4.2.5 RFA Data Type

The VAX BASIC or DEC BASIC RFA data type is an RMS-specific entity that acts like a bookmark into files for quicker RMS record retrieval. RFA usage is supported for remote OpenVMS file I/O using the Translator RMS Server. For local Windows file I/O, there is no Visual Basic data type corresponding to RFA, so the RFA is emulated as the record location within the file. This RFA emulation for local Windows file I/O is transparent to the translated program.

4.2.6 MAP, COMMON, and RECORD Declarations

As of Version 1.2 of the Translator, MAP, COMMON, and RECORD declarations in VAX BASIC or DEC BASIC are translated to Visual Basic classes, as follows:

  • Each MAP and COMMON declaration generates a Visual Basic class that simulates the storage of the variables in a PSECT shared among the modules that are translated together.
  • Each RECORD declaration is translated to a class definition. This uniformity is required to implement the MOVE [TO|FROM] translation that supports input and output of RECORD types. (In versions of the Translator previous to Version 1.2, simple DEC BASIC RECORD structures were translated to Visual Basic Type declarations, and only complicated structures became class declarations.)

For readability, the Translator generates names for the Visual Basic classes as follows:

  • A class that implements a PSECT is named by simply appending "_Class" to the PSECT name.
  • A class that implements a RECORD or GROUP structure is named by appending the structure name, the module name, and the routine name (if any), separated by underscores. As this is sufficient to distinguish it from the original name, and this generated name is already likely to be long, "_Class" is not appended to the end. Any characters in the result that are invalid in Visual Basic are respelled in the same way as they are in any user identifier.

(In versions previous to Version 1.2, the Translator included the PSECT or RECORD name, the module name, the routine name (if any) and "CLS" in the class name, and removed all "$_." characters.)

The following features apply to a translation of multiple modules in one run of the Translator with the file names on the command line separated by commas.

If (by repetition or by %INCLUDE) the same RECORD structure is declared in multiple modules, the Translator recognizes the duplication and reuses the first class in the later module. (In versions previous to Version 1.2, the Translator created a class file for each module in which the definition appeared, even if it came from a shared %INCLUDE file.)

If (by repetition or by %INCLUDE) the same PSECT variable (in a MAP or COMMON declaration) is declared in multiple modules, the Translator recognizes the duplication and reuses the already generated class member in the later module. (In versions previous to Version 1.2, the Translator created a class file for each module in which the definition appeared, even if it came from a shared %INCLUDE file.)

If the same PSECT is declared in multiple modules, and the same variable name is declared with different attributes in these modules, the modules still share one class for the translation, but later uses of the variable name will have the variable name respelled with an appended underscore and a sequence number; for example, FOO is respelled FOO_1, FOO_2, and so forth.

If multiple modules declare the same RECORD name, but the structures do not match, then each structure generates a separate class file.

GROUP Problem

If a GROUP has the same name as another GROUP or RECORD, the Translator does not detect the duplication, and so it may generate multiple class files with the same name and different OpenVMS file version numbers. Because the names conflict, the translated code will not work properly; and because the Windows file system does not have version numbers, one of the class files will be missing on the destination Windows system.

Following are two workarounds for the problem:

  • Rename one of the versions of the file and correspondingly rename the structures in the Visual Basic code, and the file names mentioned in the .VBP and .VPD files.
  • Or change the name of the GROUPs in the source program before translation so that the only GROUPs that share identical names also share identical structure. Then purge any replication of class files, and simply delete any duplicate lines in the .VBP and .VPD files.

MAP and COMMON Statements

VAX BASIC or DEC BASIC COMMON and MAP statements are used by many applications because of their usefulness in three areas:

  • They offer the only way to create project/application-wide globals within VAX BASIC or DEC BASIC.
  • They offer a powerful mechanism for manipulating records read from, and written to, ISAM files.
  • They offer great flexibility in accessing an allocated chunk of memory in various different ways.

Because Visual Basic does not support MAP and COMMON structures, MAP and COMMON behavior is emulated by other means. VAX BASIC or DEC BASIC MAP and COMMON statements are translated by generating classes that can extract from, and insert into, a predefined global buffer. When a MAP or COMMON statement is detected, the Translator keeps track of the offsets of each member within the PSECT, as well as the size of the PSECT. When translation of the current routine is complete, the Translator generates a global buffer for the PSECT using a Visual Basic Public statement. It then creates a Visual Basic Class file, setting up each member of the PSECT with a property procedure that knows how to extract from, and insert into, the offset of that member within the PSECT. These offsets are relative to the base of the PSECT, which is set once by calling the SetBase subroutine of the generated Class.

In versions previous to Version 1.2, because Visual Basic does not load a project properly if there are multiple definitions of the same class, the Translator made MAP class names unique by embedding the name of the current routine. This process could have the unwanted result of creating multiple (differently named) copies of the same MAP. After loading the code into Visual Basic, you would fix the multiple copies within Visual Basic by deleting all but one of the identical classes, while changing all occurrences of the identical classes to point to that class.

The Translator fully qualifies member names whenever they are referenced within the routine.

As of Version 1.2, the Translator names a class that implements a PSECT (that is, any class generated by a COMMON or MAP statement in the source code) by simply appending "_Class" to the PSECT name.

In versions previous to Version 1.2, the naming of variables was different. For example, consider this VAX BASIC or DEC BASIC code:


MAP (ABC) String Astr = 16
Astr = "Hello World"

This became this Visual Basic code:


Dim ABC As New ABC_MyRoutine_CLS
ABC.Astr = "Hello World"

Note the generated Dim statement.

In Version 1.2, the Dim statement in the example output is in the _GBLS file instead, and is as follows:


Dim ABC As New ABC_Class

This appears only once, no matter how many modules are translated together.

To pass a member of a MAP by reference and to allow the called routine to modify the passed member, you must pass the address of the member by value. You can get this address by the following expression:


Address = mapname.Base_Address + member_offset

Member_offset is a hardcoded numeric literal that can be found in the generated MAP class.

If you are not concerned with the ability of the called routine to modify the passed member, then just pass the member by reference. Visual Basic will create a temporary variable to hold the current value of the MAP member, then pass that temporary variable by reference. On return, the changed value is just deleted. This is not an option for members that are records.

The MAP DYNAMIC and REMAP statements are not supported. MAP DYNAMIC is converted into a standard MAP and then translated. This reduces the ability to change the offsets of members during the execution of the program. You can approximate MAP DYNAMIC features for a previously defined fixed string by using a generated MAP class. The MAP class code generated by the Translator provides an example of how to do this.

4.2.7 RECORD Statements

Record statements need special handling by the Translator, because Visual Basic does not support the VAX BASIC and DEC BASIC VARIANT structure. As of Version 1.2 of the Translator, all RECORDs are translated to Visual Basic classes and no longer are translated to Visual Basic Type declarations. This uniformity is needed for the MOVE TO and MOVE FROM statements supporting RECORD I/O.

In versions previous to Version 1.2, translation of VAX BASIC or DEC BASIC RECORD statements was handled in one of two ways, depending on the complexity of the RECORD definition:

  • For simple cases, the VAX BASIC or DEC BASIC RECORD definition was translated into an equivalent Visual Basic Type definition.
    Because Visual Basic does not have the concept of groups, any GROUP structures were pulled out as separate Visual Basic Type definitions and a field was created within the Parent Type referencing the new "Group" Type.
  • For more complex RECORD definitions and for RECORDs that are referenced by MAP members, Visual Basic classes were generated.

As with MAP, a set of property procedures is created for each field of the RECORD. These procedures know how to extract from, and insert into, an offset within a defined buffer. As with MAP, Record class name uniqueness is guaranteed across a project by inserting the current routine name into the class name. In a multiple module translation, duplicate RECORD declarations that are identical will be matched and produce only one Class file. For more information, refer to the previous MAP and COMMON Statements section.

Note that if a GROUP within a RECORD has the same name as another GROUP or RECORD, the Translator will not detect this, and will produce multiple Class files for that name, which must be resolved manually. If the GROUPs' structures are identical, the duplicate files can simply be purged.

For all field references, the Translator attempts to convert all partially qualified names to fully qualified names. This is successful when all referenced records within the field path are defined before their actual use within the routine.

To pass a record, or a field within a record, by reference, and allow the called routine to modify it, you must pass the address of the element by value. You can get this address by using one of the following expressions:

  • For Passing Records:


    Address = recordname.Base_Address
    
  • For Passing Fields:


    Address = recordname.Base_Address + field_offset
    

    Field_offset is a hardcoded numeric literal that can be found in the generated RECORD class.

If you are not concerned with the ability of the called routine to modify the passed value, then just pass the field by reference. Visual Basic will create a temporary variable to hold the current value of the field, then pass that temporary by reference. On return, the changed value is ignored. This is not an option for passing entire records or fields that are Groups.

Groups

Because Visual Basic does not have the concept of groups, any GROUP structures are pulled out as separate Visual Basic Type definitions and a field is created within the Parent Type referencing the new "Group" Type. <recto_head>(cancel_h) <verso_head>(cancel_h)


Previous Next Contents Index