mirror of
https://github.com/PDP-10/stacken.git
synced 2026-04-20 08:46:31 +00:00
2292 lines
83 KiB
Plaintext
2292 lines
83 KiB
Plaintext
%TITLE 'Library of definitions for the DIX'
|
||
!
|
||
! COPYRIGHT (C) DIGITAL EQUIPMENT CORPORATION 1983, 1986.
|
||
! ALL RIGHTS RESERVED.
|
||
!
|
||
! THIS SOFTWARE IS FURNISHED UNDER A LICENSE AND MAY BE USED AND
|
||
! COPIED ONLY IN ACCORDANCE WITH THE TERMS OF SUCH LICENSE AND WITH
|
||
! THE INCLUSION OF THE ABOVE COPYRIGHT NOTICE. THIS SOFTWARE OR
|
||
! ANY OTHER COPIES THEREOF MAY NOT BE PROVIDED OR OTHERWISE MADE
|
||
! AVAILABLE TO ANY OTHER PERSON. NO TITLE TO AND OWNERSHIP OF THE
|
||
! SOFTWARE IS HEREBY TRANSFERRED.
|
||
!
|
||
! THE INFORMATION IN THIS SOFTWARE IS SUBJECT TO CHANGE WITHOUT
|
||
! NOTICE AND SHOULD NOT BE CONSTRUED AS A COMMITMENT BY DIGITAL
|
||
! EQUIPMENT CORPORATION.
|
||
!
|
||
! DIGITAL ASSUMES NO RESPONSIBILITY FOR THE USE OR RELIABILITY OF
|
||
! ITS SOFTWARE ON EQUIPMENT THAT IS NOT SUPPLIED BY DIGITAL.
|
||
|
||
!++
|
||
! .Chapter DIXLIB
|
||
! The module DIXLIB defines global data structures and code values for
|
||
! the DIX package.
|
||
!
|
||
! This was done for two reasons: The obvious one of isolating such
|
||
! definitions to one module, and a secondary one. The secondary reason
|
||
! is that, by placing code value definitions in a library file, it is
|
||
! possible to write programs which, by calling that library file, get
|
||
! lists of code values which they write out to files in various ways.
|
||
! This allows you to implement automatic generation of interface support
|
||
! files.
|
||
!--
|
||
|
||
!++
|
||
! .HL 1 Library files used
|
||
!--
|
||
|
||
%BLISS32 ( ! ; .P;If we're BLISS 32, then
|
||
LIBRARY 'SYS$LIBRARY:XPORT'; ! \\ and
|
||
LIBRARY 'SYS$LIBRARY:STARLET'; ! \\
|
||
)
|
||
|
||
%BLISS36 ( ! ; .p;If we're BLISS 36 then
|
||
LIBRARY 'BLI:XPORT'; ! \\ and
|
||
LIBRARY 'STAR36'; ! \\
|
||
)
|
||
|
||
! ; .P;In either case,
|
||
LIBRARY 'FIELDS'; ! \\
|
||
|
||
MACRO
|
||
blf$comma =
|
||
%; ! Hack to format $OVERLAY right
|
||
|
||
%sbttl 'Edit History' ! [7] Add this entire subsection
|
||
|
||
!++
|
||
! .hl 1 Edit History
|
||
!
|
||
! The edit history/version number information in this file is used
|
||
! to build a literal, dix$k_library_version, giving the full version
|
||
! information. The history modules that use this library make an OWN
|
||
! location called dix$g_library_version and initialize it to
|
||
! dix$k_library_version. This makes it possible to tell at debug time
|
||
! what version of the library was actually compiled against.
|
||
!--
|
||
|
||
LIBRARY 'VERSION';
|
||
|
||
! ; .autotable
|
||
|
||
!++ COPY
|
||
|
||
new_version (1, 0)
|
||
|
||
edit (7, '23-Aug-82', 'David Dyer-Bennet')
|
||
%( Change version and revision standards everywhere.
|
||
Files: All. )%
|
||
|
||
edit (8, '15-Sep-82', 'David Dyer-Bennet')
|
||
%( Definition of XCGEN as pseudonym for DIX$BY_DIX_DES was missing from
|
||
DIXLIB.
|
||
Files: DIXLIB.BLI )%
|
||
|
||
Edit (%O'26', '17-Jan-83', 'David Dyer-Bennet')
|
||
%( Change error message for DIX$_IMPOSSIBLE.
|
||
Files: DIXLIB.BLI
|
||
)%
|
||
|
||
Edit (%O'30', '19-Jan-83', 'David Dyer-Bennet')
|
||
%( Update copyright notices, add mark at end of edit histories.
|
||
)%
|
||
|
||
Edit (%O'35', '7-June-83', 'Charlotte L. Richardson')
|
||
%( Declare version 1 complete. All modules.
|
||
)%
|
||
|
||
new_version (1, 1)
|
||
|
||
new_version (2, 0)
|
||
|
||
Edit (%O'36', '11-Apr-84', 'Sandy Clemens')
|
||
%( Put all Version 2 DIX development files under edit control. Some of
|
||
the files listed below have major code edits, or are new modules. Others
|
||
have relatively minor changes, such as cleaning up a comment.
|
||
FILES: COMDIX.VAX-COM, COMPDX.CTL, DIXCST.BLI, DIXDEB.BLI,
|
||
DIXDN.BLI (NEW), DIXFBN.BLI, DIXFP.BLI, DIXGBL.BLI, DIXGEN.BLI,
|
||
DIXHST.BLI, DIXINT.PR1, DIXINT.PR2, DIXLIB.BLI, DIXPD.BLI (NEW),
|
||
DIXREQ.REQ, DIXSTR.BLI, DIXUTL.BLI, DXCM10.10-CTL, MAKDIXMSG.BLI,
|
||
STAR36.BLI, VERSION.REQ.
|
||
)%
|
||
|
||
Edit (%O'50', '8-Oct-84', 'Sandy Clemens')
|
||
%( Add new format of COPYRIGHT notice. FILES: ALL )%
|
||
|
||
new_version (2, 1)
|
||
|
||
Edit (%O'51', '11-Jun-85', 'Sandy Clemens')
|
||
%( Update DIL for DIU support. Includes support complex floating-point
|
||
number conversion. FILES: DIXLIB.BLI, DIXUTL.BLI, DIXFP.BLI.
|
||
)%
|
||
|
||
Edit (%O'53', '3-Jul-86', 'Sandy Clemens')
|
||
%( Add remaining sources to V2.1 area. Update copyright notices. )%
|
||
|
||
! **EDIT**
|
||
!-- .autoparagraph
|
||
|
||
%BLISS36 (
|
||
MACRO
|
||
dix$k_library_version = %NAME ('lib%ve') %;
|
||
)
|
||
|
||
LITERAL
|
||
dix$k_library_version = version_number
|
||
(major = major_version,
|
||
minor = minor_version,
|
||
edit_no = edit_number);
|
||
|
||
UNDECLARE
|
||
major_version, minor_version, edit_number, sequence_check_edits;
|
||
%SBTTL 'Debugging Declarations'
|
||
!++
|
||
! .HL 1 Debugging Declarations
|
||
!
|
||
! There is extensive debugging code and many special definitions in
|
||
! the DIX code. All of it is conditional (at compiletime) on a literal.
|
||
! Further, if that literal is set, there are run-time variables
|
||
! defined in each module and routine that control whether any special
|
||
! debugging code actually executes. These may be poked with a debugger
|
||
! to give you dynamic control of debugging prints.
|
||
!
|
||
! >DIX$K_DEBUG controls compiletime generation of all this debugging
|
||
! code.
|
||
!
|
||
! >DIX$GG_DEBUG controls run-time debugging for the entire package.
|
||
! If this is false, no debugging prints or other code will execute.
|
||
!
|
||
! >MODULE_DEBUG (defined in each module) must be true for any debugging
|
||
! code in the module to execute. Note that, if DIX$GG_DEBUG is not true,
|
||
! the setting of MODULE_DEBUG is irrelevant.
|
||
!
|
||
! >ROUTINE_DEBUG (defined in each routine) must be true for any
|
||
! debugging code in the routine to execute. Note that, if DIX$GG_DEBUG or
|
||
! MODULE_DEBUG is not true, the setting of ROUTINE_DEBUG is irrelevant.
|
||
!
|
||
! >DEBUG_FLAG is dynamically bound at the start of each routine to
|
||
! be the logical AND of the above three flags. This is the flag that
|
||
! actual debugging code checks.
|
||
!--
|
||
|
||
!++
|
||
! The require file >DIXDEB.REQ does nothing but define a value for
|
||
! >dix$k_debug>, a literal. By doing the require within the library file,
|
||
! debugging/non-debugging becomes an attribute of the version of DIXLIB
|
||
! with which other modules are compiled.
|
||
!--
|
||
|
||
REQUIRE 'DIXDEB';
|
||
|
||
!++
|
||
! .hl 2 Debugging macros
|
||
!
|
||
! Described below are macros which help set up and use the debugging
|
||
! control fields:
|
||
!--
|
||
|
||
MACRO
|
||
DIX$DEBUG ! \.HL 3 >\
|
||
!++
|
||
! This macro expands to its arguments (%REMAINING) if
|
||
! dix$k_debug is true, to null otherwise.
|
||
!--
|
||
[] = ! ; This is a conditional macro with no arguements.
|
||
%IF dix$k_debug %THEN %REMAINING %FI %,
|
||
DIX$module_debug ! \.hl 3 >\
|
||
!++
|
||
! This macro defines MODULE_DEBUG as its argument. It should
|
||
! be called at the start of every module. It should not be followed
|
||
! by a semi-colon.
|
||
!
|
||
! Arguments:
|
||
!--
|
||
( ! ; .s 1.list 1
|
||
module_debug_flag ! \.le;\: True if debugging wanted
|
||
) = ! ; .end list
|
||
DIX$DEBUG (OWN module_debug: INITIAL (module_debug_flag) VOLATILE;
|
||
EXTERNAL dix$GG_debug;)
|
||
% ,
|
||
dix$routine_debug ! \.hl 3 >\
|
||
!++
|
||
! This macro defines ROUTINE_DEBUG as its argument. It should be
|
||
! called at the start of every routine. It should not be followed
|
||
! by a semi-colon.
|
||
!
|
||
! Arguments:
|
||
!--
|
||
( ! ; .s 1.list 1
|
||
routine_debug_flag ! \.le;\: True if debugging wanted
|
||
) = ! ; .end list
|
||
DIX$DEBUG (OWN routine_debug: INITIAL (routine_debug_flag);
|
||
BIND debug_flag = .DIX$GG_DEBUG AND .module_debug AND .routine_debug;
|
||
) %,
|
||
debug_code ! \.hl 3 >\
|
||
!++
|
||
! This macro expands to its arguments if dix$k_debug is set at
|
||
! compile time. It executes the code generated if debug_flag is
|
||
! set at run-time. Executable debugging code should be included
|
||
! within a call to debug-code.
|
||
!
|
||
! This macro expands to an expression that performs the indicated
|
||
! tasks. It may be used without bracketing in contexts where a
|
||
! single expression/statement is required. Where it is not being
|
||
! used as an expression, it should be followed by a semi-colon.
|
||
! This may result in null expressions when debugging is turned
|
||
! off at compiletime.
|
||
!--
|
||
[] = ! ; This is a conditional macro with no arguements.
|
||
dix$debug (IF debug_flag THEN BEGIN %REMAINING END) % ;
|
||
|
||
!++
|
||
! .HL 2 Terminal I/O macros
|
||
! These macros look and perform like the macros defined in TUTIO, but
|
||
! they function by calling external routines defined in DIXDEB. (The
|
||
! routines called perform their functions by calling TUTIO).
|
||
!
|
||
! The Terminal Output Macros are intended to make it easier to
|
||
! print on the terminal, especially during debugging.
|
||
!
|
||
! >TUTIO does various system-dependent things including searching
|
||
! libraries and defining globals. I'm having enough trouble balancing
|
||
! that sort of thing across systems that I don't need somebody else
|
||
! helping, so I isolated that stuff to DIXDEB. Note that DIXDEB must
|
||
! also search DIXLIB. To avoid having these definitions conflict with
|
||
! the definitions in TUTIO, I did some undeclaring in DIXDEB (q.v.).
|
||
!
|
||
! The macros defined here are:
|
||
!--
|
||
|
||
MACRO ! ;.s 1 .list 1, "o"
|
||
tty_put_quo (str_lit) = ! \.le;MACRO >\ Type quoted string literal.
|
||
typasz (UPLIT (%ASCIZ str_lit)) %,
|
||
tty_put_crlf (dummy) = ! \.le;MACRO >\ Type a cr/lf.
|
||
typnel () %,
|
||
tty_put_integer (int, rad, lng) = ! \.le;MACRO >\ Type value of integer.
|
||
typint (int, rad, lng) %,
|
||
tty_get_integer (rad) = ! \.le;MACRO >\ Get integer from terminal.
|
||
ttygin (rad) %;
|
||
|
||
|
||
MACRO
|
||
dtype (crlf) [] = ! \.le;MACRO >\Type if DEBUG_FLAG set.
|
||
!++
|
||
! If debug_code (defined above) is satisfied,
|
||
! this types a mixed bag of quoted string and integer
|
||
! items on the terminal (it uses the standard tty_put_quo and
|
||
! tty_put_integer macros to get to the terminal). The first actual
|
||
! controls whether a crlf is put out at the end of the line -- 1 means
|
||
! yes, 0 means no.
|
||
!
|
||
! To type a quoted string, simply place the string in the argument
|
||
! list. To type the value of an expression, put the expression in the
|
||
! argument list. The default radix is decimal, the default field
|
||
! width is 11. To override these, specify (exp, length, radix) (the
|
||
! parens are vital). The radix may be omitted to override just
|
||
! the length.
|
||
!
|
||
! Both this and TERMO (below) produce an expression. You supply your
|
||
! own semi-colon if that's what you want.
|
||
!--
|
||
debug_code (termo (crlf, %REMAINING))
|
||
% ,
|
||
termo (crlf) [] = ! \.le;MACRO >\Type mixed quoted strings and integers.
|
||
!++
|
||
! This is exactly like dtype above, except for the dependency on
|
||
! debugging flags.
|
||
!--
|
||
BEGIN ! This provides left context for iterative macro pr1
|
||
pr1 (%REMAINING) ;
|
||
|
||
%IF crlf %THEN
|
||
tty_put_crlf ()
|
||
%FI
|
||
END
|
||
% ,
|
||
pr1 [item] = ! \.le;MACRO >\Type n generic items.
|
||
!++
|
||
! Type out an arbitrary number of generic items (this is an iterative
|
||
! macro with no fixed parameters).
|
||
!--
|
||
pr2 (%REMOVE (item)) %, !
|
||
pr2 (item, length, base) = ! \.le;MACRO >\Type one generic item.
|
||
!++
|
||
! Type exactly one generic item. This is a simple macro except
|
||
! for the kludge to supply default values for missing arguments.
|
||
!
|
||
!.end list
|
||
!--
|
||
%IF %ISSTRING (item) %THEN
|
||
tty_put_quo (item)
|
||
%ELSE
|
||
tty_put_integer ((item),
|
||
(%IF %LENGTH GTR 2 %THEN ! Fudge a default value
|
||
base
|
||
%ELSE
|
||
10 ! Default base is 10
|
||
%FI)
|
||
,
|
||
(%IF %LENGTH GTR 1 %THEN ! Fudge a default value
|
||
length
|
||
%ELSE
|
||
11 ! Default length is 11
|
||
%FI)
|
||
)
|
||
%FI
|
||
%;
|
||
|
||
%SBTTL 'Misc declarations'
|
||
!++
|
||
! .HL 1 Miscellaneous declarations
|
||
! These assorted declarations go here so that they can be referred to
|
||
! later in the file. A few more miscellaneous declarations
|
||
! (system-dependent) are put in the require file >DIXREQ.REQ>. They
|
||
! are there only when BLISS or system restrictions force that for one
|
||
! system or another.
|
||
! .s1
|
||
!--
|
||
|
||
LITERAL
|
||
unit_offset_size = %BLISS16 (3) %BLISS32 (3) %BLISS36 (6); ! \ >\ This is the number of bits required
|
||
! ;to represent the maximum bit offset within an addressable unit on the
|
||
! ;current host system. It is used for optimizing structure declarations on
|
||
! ;each system.
|
||
|
||
!++
|
||
! Small-integer codes for the various types of systems which the DIX
|
||
! must know about:
|
||
! .list 0, " "
|
||
!--
|
||
|
||
$literal
|
||
sys_lcg = $distinct, ! \.le;>\ (36-bit addressable systems),
|
||
sys_8bit = $distinct, ! \.le;>\ (8-bit addressable systems),
|
||
sys_ult = $distinct; ! \.le;>\ (for hackery),
|
||
|
||
LITERAL
|
||
sys_max = sys_ult - 1; ! \.le;>\ (max sys code assigned).
|
||
! ;.end list
|
||
!++
|
||
! Define macro >readonly_psect which expands to the name of a
|
||
! write-protected psect on whatever system we are compiling on. This
|
||
! lets me put static data tables into the sharable part of the image
|
||
! in a manner that looks system-independent in the later code.
|
||
!--
|
||
|
||
MACRO
|
||
readonly_psect = %BLISS36 ($HIGH$) %BLISS32 ($PLIT$) % ;
|
||
|
||
!++
|
||
! Convenience names for booleans:
|
||
! .list 0, " "
|
||
!--
|
||
LITERAL
|
||
true = 1, false = 0, ! \.le;
|
||
on = 1, off = 0; ! \.le;
|
||
! ;.end list
|
||
%SBTTL 'Array structure'
|
||
!++
|
||
! .HL 1 Array structure
|
||
! The structure >ARRAY is defined as a two-dimensional array of
|
||
! fullwords with minimum and maximum subscript bounds for each dimension
|
||
! specified by the user. This was implemented for the table
|
||
! >gen_dispatch_tbl in module DIXGEN, which lets you look up a routine
|
||
! address given a source and destination data-type.
|
||
!--
|
||
|
||
STRUCTURE array [row, col; row_min, row_max, col_min, col_max] =
|
||
[(row_max - row_min + 1) * (col_max - col_min + 1) * %UPVAL]
|
||
(array + ((col - col_min) + (row - row_min) * (row_max - row_min + 1)) * %UPVAL);
|
||
%SBTTL 'Foreign Field Descriptor (FFD)'
|
||
|
||
!++
|
||
! .HL 1 The Foreign Field Descriptor (FFD)
|
||
!
|
||
! This structure is the descriptor used to describe a foreign field
|
||
! anywhere within the DIX package. The structure code is >FFD.
|
||
!
|
||
! A single occurrence of an FFD points to and identifies a (foreign
|
||
! or local) field somewhere in local memory. This is the structure
|
||
! used to identify a field to the conversion routines (below the user
|
||
! interface level).
|
||
!
|
||
! .index data type codes
|
||
! A data type code has two parts: a data class code, and a
|
||
! within-class type code. The classes are as described in the
|
||
! functional specification: string, fixed binary, floating point,
|
||
! boolean, complex, display-numeric, packed decimal, etc. The sizes
|
||
! of the fields are controlled by the following parameters:
|
||
!--
|
||
|
||
LITERAL
|
||
class_code_bits = 4, ! \.P;\Size of data class code
|
||
type_code_bits = 8; ! \.P;\Size of within-class type code
|
||
|
||
|
||
!++
|
||
! Here are the field definitions for the FFD:
|
||
! .s 1
|
||
! .literal
|
||
!--
|
||
|
||
!++ copy
|
||
MACRO ffd_flds (prefx) = ! THIS MACRO IS ADDED FOR DIU.
|
||
! IT WILL MAKE THE TRANSFORM STRUCTURE
|
||
! EASIER TO KEEP COMPATIBLE WITH DIL.
|
||
|
||
%NAME (prefx, '$v_unit') = [$address], ! Address of lowest unit
|
||
! containing some bit of the
|
||
! field
|
||
%NAME (prefx, '$v_length') = [$bits (16)], ! Length of field in "natural"
|
||
! units (listed explicitly
|
||
! with data type definitions)
|
||
%NAME (prefx, '$v_scale') = [$short_integer], ! Scale factor for fixed-point
|
||
! decimal-based data types
|
||
%NAME (prefx, '$v_offset') = [$bits (unit_offset_size)], ! Bit offset within
|
||
! addressable unit to
|
||
! low-order bit of
|
||
! field
|
||
%NAME (prefx, '$v_type') = [$bits (class_code_bits + type_code_bits)],
|
||
! Data type code
|
||
$overlay (%NAME (prefx, '$v_type')) blf$comma
|
||
%NAME (prefx, '$v_dt_type') = [$bits (type_code_bits)], ! Type subfield
|
||
%NAME (prefx, '$v_dt_class') = [$bits (class_code_bits)], ! Class subfield
|
||
$continue
|
||
%NAME (prefx, '$v_align') = [$bits (6)], ! Bit offset within original
|
||
! system addressable unit to
|
||
! low-order bit of field
|
||
%NAME (prefx, '$v_sys_orig') = [$bits (2)] ! system of origin code
|
||
%;
|
||
|
||
$field
|
||
|
||
ffd_fields =
|
||
SET
|
||
ffd_flds ('ffd')
|
||
TES;
|
||
|
||
LITERAL
|
||
ffd$k_size = $field_set_size;
|
||
!-- .END LITERAL
|
||
|
||
!++
|
||
! To declare a data segment to be of type FFD, use the >forgn_descr
|
||
! macro in place of the structure and field attributes in the data
|
||
! declaration. It works with both immediate and REF structures.
|
||
!--
|
||
|
||
MACRO
|
||
forgn_descr =
|
||
BLOCK [ffd$k_size]
|
||
|
||
FIELD
|
||
(ffd_fields) %;
|
||
|
||
!++
|
||
! .hl 2 Data type codes
|
||
!
|
||
! Data type codes are sometimes accessed outside of an FFD. These
|
||
! definitions give you access to the fields from a fullword value.
|
||
!--
|
||
|
||
FIELD
|
||
dt_fields =
|
||
SET ! ;.list 0, "o"
|
||
dt_class_sep = ! \.le;>\Data class code only
|
||
[0, type_code_bits, %BPVAL - type_code_bits, 0],
|
||
! Make sure def looks at whole word,
|
||
! or garbage may sneak through
|
||
dt_code_sep = ! \.le;>\With-in class type code only
|
||
[0, 0, type_code_bits, 0]
|
||
TES; ! ;.end list
|
||
|
||
MACRO
|
||
data_type_sep = BLOCK [1] FIELD (dt_fields) % ;
|
||
%SBTTL 'DEC-10/20 standard calling sequence'
|
||
|
||
!++
|
||
! .hl 1 DEC-10/20 Standard Calling Sequence
|
||
!
|
||
! Define symbolic names for various fields used in processing
|
||
! routine calls made through the standard calling sequence on tens and
|
||
! twenties.
|
||
!--
|
||
|
||
!++
|
||
! First, entries in the standard calling sequence argument list have
|
||
! various fields within them:
|
||
! .list 1, "o"
|
||
!--
|
||
|
||
FIELD
|
||
scs_arg_fields =
|
||
SET
|
||
scs$v_type = [0, 23, 4, 0], ! \.le;\Type of argument
|
||
scs$v_adr = [0, 0, 23, 0] ! \.le;\Address of argument or descriptor
|
||
TES;
|
||
|
||
! ;.end list
|
||
|
||
!++
|
||
! To declare a data-segment to be of type scs_arg, use the macro
|
||
! >scs_arg in place of the structure and field attributes in the data
|
||
! declaration. This is useful for code which must see inside the
|
||
! structure of the standard calling sequence, such as routines that
|
||
! interpret descriptors.
|
||
!--
|
||
|
||
MACRO
|
||
scs_arg =
|
||
BLOCK [1]
|
||
|
||
FIELD
|
||
(scs_arg_fields) %;
|
||
|
||
!++
|
||
! The type code field in a data-segment of type scs_arg has the
|
||
! following possible meanings:
|
||
! .list 1, "o"
|
||
!--
|
||
|
||
LITERAL
|
||
!++ copy /strip .le;>
|
||
scs$k_unspecified = 0, ! [2] Unspecified type (assume its right)
|
||
scs$k_for36_bool = 1, ! FORTRAN-10/20 Boolean
|
||
scs$k_sbf36 = 2, ! DEC-10/20 one-word integer
|
||
scs$k_float36 = 4, ! DEC-10/20 one-word floating
|
||
scs$k_rtnadr = 7, ! The address of a routine
|
||
scs$k_float72 = %O'10', ! DEC-10/20 two-word floating (not G)
|
||
scs$k_sbf72 = %O'11', ! DEC-10/20 two-word integer
|
||
scs$k_fcmplx36 = %O'14', ! DEC-10/20 single-precision complex
|
||
scs$k_display = %O'15', ! 'address' points to descriptor
|
||
scs$k_asciz = %O'17'; ! DEC-10/20 ASCII string terminated by NUL
|
||
!-- .END LIST
|
||
|
||
!++
|
||
! And now, the fields of the full SCS descriptor. See the COBOL-74
|
||
! Language Reference Manual for the official definition of this
|
||
! descriptor:
|
||
!
|
||
! .s 1.literal
|
||
!--
|
||
|
||
!++ copy
|
||
FIELD
|
||
scs_descriptor_fields =
|
||
SET
|
||
scs$v_bytpntr = [0, 0, 36, 0],
|
||
scs$v_bytsiz = [0, 24, 6, 0],
|
||
scs$v_numflg = [1, 35, 1, 0],
|
||
scs$v_pscalflg = [1, 23, 1, 0],
|
||
scs$v_scalfac = [1, 18, 5, 1],
|
||
scs$v_lng = [1, 0, 18, 0]
|
||
TES;
|
||
!-- .end literal
|
||
|
||
!++
|
||
! To declare a data-segment as type SCS descriptor, use the
|
||
! >scs_descr macro in place of the structure and field attributes in
|
||
! the data declaration.
|
||
!--
|
||
|
||
MACRO
|
||
scs_descr =
|
||
BLOCK [2]
|
||
|
||
FIELD
|
||
(scs_descriptor_fields) %;
|
||
|
||
!++
|
||
! To get at unit-aligned data passed using the SCS without knowing its type,
|
||
! use argadr (.foo) instead of .foo and .(argadr (.foo)) instead of ..foo.
|
||
!
|
||
! The macro for BLISS32 is defined simply for compatibility.
|
||
! The BLISS36 variant does more -- it calls dix$$get_argadr, which returns
|
||
! the address of the unit in which the field starts, regardless of the type
|
||
! of the field. Remember, this works only for unit-aligned data.
|
||
!--
|
||
|
||
%BLISS36 (
|
||
MACRO
|
||
argadr (foo) = dix$$get_argadr (foo) % ;
|
||
)
|
||
|
||
%BLISS32 (
|
||
MACRO
|
||
argadr (foo) = foo % ; ! [3]
|
||
)
|
||
%SBTTL 'MACRO36 linkage declaration'
|
||
|
||
%IF %BLISS (BLISS36)
|
||
%THEN
|
||
|
||
!++
|
||
! .HL 1 MACRO36 linkage declaration
|
||
! .index macro36 linkage
|
||
! This linkage is particularly convenient for calling MACRO subroutines from
|
||
! BLISS36.
|
||
!
|
||
! The standard stack (17) and frame pointers (15) are used. Register
|
||
! 0 is the value return register. The first five parameters are
|
||
! passed in registers 1 through 5. Further parameters would be passed
|
||
! on the stack, in the "standard" way for PUSHJ linkage. If you have
|
||
! that many parameters to a MACRO subroutine, think about changing
|
||
! something.
|
||
!--
|
||
|
||
LINKAGE
|
||
macro36 = PUSHJ (REGISTER = 1, REGISTER = 2, REGISTER = 3, REGISTER = 4, REGISTER = 5) : !
|
||
LINKAGE_REGS (15, 13, 0) ! 17, 15, 0 in decimal
|
||
PRESERVE (6, 7, 8, 9, 10);
|
||
|
||
%FI
|
||
|
||
%sbttl 'Intermediate Forms'
|
||
!++
|
||
! .HL 1 Intermediate Forms
|
||
!--
|
||
|
||
!++
|
||
! .HL 2 CANONICAL BINARY (CB)
|
||
! .INDEX CANONICAL BINARY
|
||
! .index cb -- canonical binary
|
||
!
|
||
! The CB (canonical binary) format represents an arbitrary precision
|
||
! binary integer as a multi-digit number in some large base which fits
|
||
! comfortably into a BLISS fullword value on the system compiled for.
|
||
!--
|
||
|
||
LITERAL
|
||
cb$k_precision = 128, ! \.p;\Constant precision, in bits of
|
||
! ; twos-complement precision.
|
||
cb$k_base_bits = %BPVAL - 6, ! \.p;\Largest calculation that must
|
||
! ; be done on a CB segment is seg * 10 + carry, where carry is
|
||
! ; no larger than a segment in practical cases. Thus, this segment
|
||
! ; size lets the largest calculation done from segments fit in a
|
||
! ; fullword without using the sign bit.
|
||
cb$k_base = 1^cb$k_base_bits, ! ;.p;cb$k_base = 1`^cb$k_base_bits, The actual base.
|
||
cb$k_segments = cb$k_precision / cb$k_base_bits + 1; ! \.p;\Number of digits needed
|
||
! ; in selected base to represent the
|
||
! ; required precision.
|
||
|
||
%PRINT (cb$k_precision , '=', %NUMBER (cb$k_precision ))
|
||
%PRINT (cb$k_base_bits , '=', %NUMBER (cb$k_base_bits ))
|
||
%PRINT (cb$k_base , '=', %NUMBER (cb$k_base ))
|
||
%PRINT (cb$k_segments , '=', %NUMBER (cb$k_segments ))
|
||
|
||
$show (fields)
|
||
$field
|
||
cb_fields =
|
||
SET
|
||
cb$v_dig = [$bits (cb$k_base_bits)],
|
||
cb$v_oflo = [$bit],
|
||
$overlay (cb$v_dig)
|
||
cb$v_fill = [$bits (cb$k_base_bits - 1)],
|
||
cb$v_sign = [$bit],
|
||
$continue
|
||
$overlay (cb$v_dig)
|
||
cb$v_all = [$integer]
|
||
$continue
|
||
TES;
|
||
MACRO
|
||
cb = BLOCKVECTOR [cb$k_segments, 1] FIELD (cb_fields) % ;
|
||
|
||
!++
|
||
! .HL 2 Fixed Intermediate Form (XI)
|
||
! .INDEX FIXED INTERMEDIATE FORM
|
||
! .INDEX XI -- fixed intermediate form
|
||
! This is the internal intermediate form used for all decimal-based types.
|
||
! It will also be used for floating-binary to decimal based, when that is
|
||
! implemented.
|
||
! A number in fixed intermediate form consists of a signed binary scale
|
||
! factor, a sign, and an unsigned decimal integer. The actual value can be
|
||
! computed as (sign * integer * 10 ** scale).
|
||
! Parameters are as follows:
|
||
!--
|
||
|
||
LITERAL ! ;.s1 .list 0, "o"
|
||
xi$k_digits = 39, ! \.le;>\(number of digits to store)
|
||
xi$k_scale_bits = 16; ! \.le;>\(number of bits for scale factor)
|
||
! ;.end list
|
||
STRUCTURE
|
||
xi_structure ! \.hl 3 Structure >
|
||
!++
|
||
! This structure is used to represent a number in fixed intermediate form.
|
||
!
|
||
! Access formals:
|
||
!--
|
||
[ ! ; .s 1.list 1
|
||
type, ! \.le;\: 0 = scale, 1 = sign, 2 = digit
|
||
digit_number ! \.le;\: selects digit 0 thru max (max is xi$k_digits)
|
||
; ! ; .end list
|
||
! ; .P;Allocation formals:
|
||
! ; .s 1.list 1
|
||
digits, ! \.le;\: Number of digits of precision
|
||
scale_bits ! \.le;\: Number of bits for scale factor
|
||
] = ! ; .end list
|
||
|
||
! ; .P;Size of space to allocate (in addressable units):
|
||
[(scale_bits + 1) / %BPUNIT + SIGN ((scale_bits + 1) MOD %BPUNIT) +
|
||
! ; Scale + sign are in one set of units,
|
||
digits / (%BPUNIT / 4) + SIGN (digits MOD (%BPUNIT / 4))]
|
||
! ; the digits are in another.
|
||
|
||
! ; .P;Field reference actually made is complicated. Note that the whole
|
||
! ; mess is a compile-time constant expression if the actuals are (which they
|
||
! ; often will be, particularly the first one).
|
||
(xi_structure + (CASE type FROM 0 TO 2 OF
|
||
SET
|
||
[0]: 0; ! Scale
|
||
[1]: scale_bits / %BPUNIT; ! Sign
|
||
[2]: (scale_bits + 1) / %BPUNIT +
|
||
SIGN ((scale_bits + 1) MOD %BPUNIT) +
|
||
digit_number * 4 / %BPUNIT;
|
||
TES)
|
||
) <(CASE type FROM 0 TO 2 OF
|
||
SET
|
||
[0]: 0; ! Scale
|
||
[1]: scale_bits MOD %BPUNIT; ! Sign is past scale
|
||
[2]: (digit_number * 4) MOD %BPUNIT;
|
||
TES),
|
||
(CASE type FROM 0 TO 2 OF
|
||
SET
|
||
[0]: scale_bits; ! Scale
|
||
[1]: 1; ! Sign
|
||
[2]: 4; ! Digit
|
||
TES),
|
||
(CASE type FROM 0 TO 2 OF
|
||
SET
|
||
[0]: 1; ! Scale is signed
|
||
[1, 2]: 0; ! Others are unsigned
|
||
TES)
|
||
>;
|
||
|
||
FIELD
|
||
xi_fields = ! ;.hl 2 Field Set XI_fields
|
||
!++
|
||
! These fields allow the user to refer to the parts of an XI field
|
||
! conveniently.
|
||
!--
|
||
SET
|
||
xi$v_scale = [0, 0], ! \.p;>\Scale factor.
|
||
xi$v_sign = [1, 0], ! \.p;>\Sign.
|
||
xi$v_digit = [2] ! \.p;>\A digit. User supplies digit number following.
|
||
TES;
|
||
|
||
MACRO
|
||
xi = xi_structure [xi$k_digits, xi$k_scale_bits] FIELD (xi_fields) % ;
|
||
|
||
!++
|
||
! .hl 2 Canonical Floating point (CF)
|
||
! .index canonical floating point
|
||
! .entry cf -- canonical floating point
|
||
!
|
||
! The Canonical Floating point (CF) form represents a number as a sort of
|
||
! generic binary floating point. The relatively large mantissa is represented
|
||
! as a series of segments of some convenient size (i.e. a compile-time
|
||
! parameter).
|
||
!
|
||
! This form is used in internal processing of floating point numbers being
|
||
! converted. By converting all specific forms to this canonical form before
|
||
! processing, the need to implement all needed operations on all needed
|
||
! representations is avoided.
|
||
!
|
||
! A number in CF form consists of three pieces: A three-valued sign
|
||
! (positive, zero, and negative), a large binary mantissa, and a large
|
||
! signed (twos-complement) exponent.
|
||
!
|
||
! The exponent occupies a fullword. Each segment of the mantissa
|
||
! occupies a fullword. Thus, unfortunately, the sign occupies a
|
||
! fullword. There is no point in attempting to minimize space used,
|
||
! since only one of these things will be allocated at any given time
|
||
! anyway. Speed of access is much more important.
|
||
!
|
||
! The mantissa segment of index 0 is considered the highest order
|
||
! segment. Segments of increasing index contain bits of decreasing
|
||
! significance. This ordering, which the opposite of the way significance
|
||
! goes everywhere else, is used because the mantissa is normally processed from
|
||
! high order to low order, and in fact the uncertainty in its length
|
||
! is at the low order, not the high order, end.
|
||
!
|
||
! Parameters are as follows:
|
||
! .list 0, "o"
|
||
!--
|
||
|
||
LITERAL
|
||
! ;.no justify
|
||
cf$k_mantissa_bits = 113, ! \.le;\Minimum mantissa bits
|
||
cf$k_mantissa_seg_bits = %BPVAL - 2, ! \.le;\Segment size
|
||
cf$k_mantissa_segs = (cf$k_mantissa_bits - 1) / cf$k_mantissa_seg_bits + 1, ! \.le;\Number of segments
|
||
! ;.justify
|
||
! ;.end list
|
||
! ; Sign values are
|
||
! ;.list 0, "o"
|
||
cf$k_sign_pos = 1, ! \.le;\: positive,
|
||
cf$k_sign_zero = 2, ! \.le;\: zero,
|
||
cf$k_sign_neg = 3; ! \.le;\: negative.
|
||
! ;.end list
|
||
! ; The order of the sign values is important to the continued well-being
|
||
! ; of the code that uses them.
|
||
|
||
STRUCTURE
|
||
cf_structure ! \.hl 3 structure >
|
||
!++
|
||
! The cf_structure (canonical floating point structure) is used to
|
||
! represent a number in canonical binary form.
|
||
!
|
||
! Access formals:
|
||
!--
|
||
|
||
[ ! ; .s 1.list 1
|
||
type, ! \.le;\: 0 = sign, 1 = exponent, 2 = mantissa
|
||
seg_ndx ! \.le;\: Select segs 0 to max if type is mantissa.
|
||
; ! ; .end list
|
||
! ; Allocation formals:
|
||
! ;.s 1.list 1
|
||
segments ! \.le;\: Number of segments
|
||
] = ! ;.end list
|
||
|
||
! ; Size of space to allocate (in addressable units):
|
||
[(segments + 2) * %UPVAL] ! ; specified number of segments + 2.
|
||
|
||
! ; Field reference actually made is relatively complicated. Note that the
|
||
! ; first case, at least, is a compile-time constant. If all the actuals are
|
||
! ; compile-time constants, the result full reference is.
|
||
(cf_structure + ! unit address
|
||
( ! offset from structure start
|
||
CASE type FROM 0 TO 2 OF
|
||
SET
|
||
[0]: 0; ! Sign
|
||
[1]: 1 * %UPVAL; ! Exponent
|
||
[2]: (2 + seg_ndx) * %UPVAL;! Segment
|
||
TES) ! offset from structure start
|
||
) ! unit address
|
||
< ! Field reference
|
||
0, ! Bit offset
|
||
%BPVAL, ! Field width,
|
||
( ! Sign
|
||
CASE type FROM 0 TO 2 OF
|
||
SET
|
||
[0,2]: 0; ! Sign and segments are unsigned
|
||
[1]: 1; ! Exponent is signed
|
||
TES
|
||
) ! Sign
|
||
>; ! Field reference
|
||
|
||
FIELD
|
||
cf_fields = ! ;.hl 2 Field Set CF_fields
|
||
!++
|
||
! These fields allow the user to refer to the parts of a CF field
|
||
! conveniently.
|
||
!--
|
||
SET
|
||
cf$v_sign = [0,0], ! \.p;>\Sign.
|
||
cf$v_exponent = [1,0], ! \.p;>\Exponent.
|
||
cf$v_mantissa = [2] ! \.p;>\Mantissa segment. User
|
||
! ; supplies segment index following.
|
||
TES;
|
||
|
||
MACRO
|
||
cf = cf_structure [cf$k_mantissa_segs] FIELD (cf_fields) % ;
|
||
|
||
%SBTTL 'Condition handling and status values'
|
||
|
||
!++
|
||
! .hl 1 Condition handling and status values
|
||
! Define general condition handling and status value structures and literals.
|
||
! We use the VAX-based status-value (condition-value) concept
|
||
! described in the BLISS language manual chapter on condition handling.
|
||
! >STS is the standard naming-prefix for the status-code facility.
|
||
! Specific values for conditions are defined in another section.
|
||
!--
|
||
|
||
!++
|
||
! .hl 2 Facility Name
|
||
! The macro >DIX$facility_name expands to the facility prefix for the
|
||
! DIX. This is used within macros that construct names from their
|
||
! parameters.
|
||
!--
|
||
|
||
MACRO
|
||
DIX$facility_name =
|
||
'DIX' %;
|
||
|
||
LITERAL
|
||
!
|
||
! ;.hl 2 Facility code
|
||
!
|
||
dix$k_facility = 232; ! \.P;>\This is the formally registered
|
||
! ; DIX facility code (registered in
|
||
! ; VAX-land).
|
||
!++
|
||
! To declare a data segment to be of type condition_value, use the
|
||
! >condition_value macro instead of the structure and field attributes
|
||
! in the data declaration.
|
||
!--
|
||
|
||
MACRO
|
||
condition_value =
|
||
BLOCK [1]
|
||
! STARLET avoids the need to declare these fields, so we have to follow suit.
|
||
! FIELD
|
||
! (
|
||
! sts$v_severity,
|
||
! sts$v_success,
|
||
! sts$v_cond_id,
|
||
! sts$v_msg_no,
|
||
! sts$v_fac_sp,
|
||
! sts$v_code,
|
||
! sts$v_fac_no,
|
||
! sts$v_cust_def
|
||
! )
|
||
% ;
|
||
|
||
!++
|
||
! The keyword macro >sts$value generates a numeric condition value
|
||
! in the format suitable for the system on which it was compiled. The
|
||
! keywords and defaults are as follows:
|
||
! .list 0, "o"
|
||
!--
|
||
|
||
KEYWORDMACRO
|
||
sts$value (
|
||
!++ copy /strip .le;
|
||
severity = sts$k_severe,
|
||
CODE,
|
||
fac_sp = 1, ! Default is facility specific
|
||
fac_no = 0, ! Customer use desires this default
|
||
cust_def = 0 ! Default is Digital defined
|
||
!-- .end list
|
||
) =
|
||
(
|
||
position_field (sts$m_severity, severity) OR
|
||
position_field (sts$m_CODE, CODE) OR
|
||
position_field (sts$m_fac_sp, fac_sp) OR
|
||
position_field (sts$m_fac_no, fac_no) OR
|
||
position_field (sts$m_cust_def, cust_def)
|
||
)
|
||
%;
|
||
|
||
%SBTTL 'Define conditions used by the DIX'
|
||
|
||
!++
|
||
!
|
||
! .hl 1 Conditions used by the DIX
|
||
!
|
||
! All the conditions used by the DIX are defined here.
|
||
!
|
||
! Each definition results in a literal of the form DIX$_name whose
|
||
! value is the condition with the default severity. The message
|
||
! numbers are assigned sequentially using the compiletime variable
|
||
! >cnd_seq>.
|
||
!
|
||
! The macro >DIX$DEF_CONS is also defined. When expanded, it
|
||
! generates calls to a user-defined macro >COND_DAT, passing the
|
||
! full condition name as a string literal ('DIX$_name'), the
|
||
! FORTRAN pseudonym (6 chars) as a string literal, the
|
||
! condition value as a numeric literal, and the text of the standard
|
||
! message as a string literal.
|
||
!
|
||
! To make a list of condition names and messages, for example, you
|
||
! would do the following: Write a program that searched this library.
|
||
! Define COND_DAT to build the data structures you want containing
|
||
! selected condition information. Then call DIX$DEF_CONS. You now
|
||
! have your data structures containing everything you wanted to print.
|
||
! It should be a simple problem to print it out.
|
||
!--
|
||
|
||
COMPILETIME
|
||
cnd_seq = 0;
|
||
|
||
MACRO
|
||
! ; Macro information:
|
||
DIX$def_con (cond_nam, fort_pseud, default_severity, msg_txt) = ! \ .P;>\
|
||
|
||
%QUOTE %EXPAND %ASSIGN (cnd_seq, cnd_seq + 1) !
|
||
%QUOTE %EXPAND %PRINT !
|
||
( ! Begin %PRINT actuals
|
||
cond_nam, ! %PRINT actual
|
||
' code is ', ! %PRINT actual
|
||
%QUOTE %EXPAND %NUMBER (cnd_seq) ! %PRINT actual
|
||
) ! End %PRINT actuals
|
||
cond_dat !
|
||
( ! Begin cond_dat actuals
|
||
%QUOTE %EXPAND %NAME ! cond_dat actual
|
||
( ! Begin %NAME actuals
|
||
%QUOTE %EXPAND DIX$facility_name, ! %NAME actual
|
||
'$_', ! %NAME actual
|
||
cond_nam ! %NAME actual
|
||
), ! End %NAME actuals
|
||
fort_pseud, ! cond_dat actual
|
||
%QUOTE %EXPAND sts$value ! cond_dat actual
|
||
( ! Begin sts$value actuals
|
||
fac_no = DIX$k_facility, ! sts$value actual
|
||
CODE = %QUOTE %EXPAND %NUMBER(cnd_seq), ! sts$value actual
|
||
severity = (default_severity) ! sts$value actual
|
||
), ! End sts$value actuals
|
||
msg_txt ! cond_dat actual
|
||
) ! End cond_dat actuals
|
||
%, ! end DIX$def_con definition
|
||
!++
|
||
! .hl 2 >DIX$def_cons details
|
||
! Definitions of new conditions should be put into the macro definition
|
||
! in a manner consistent with the existing entries:
|
||
! .i 5;%EXPAND DIX$def_con ('name', 'fortpseud', default-severity, 'message text')
|
||
! In particular, note the absence of commas and semicolons at the end of
|
||
! the macro call to DIX$def_con.
|
||
! The "%EXPAND" is necessary to cause the generation of message
|
||
! codes to occur at library compile time. It is necessary that
|
||
! literal values be contained in the defined DIX$def_cons so that
|
||
! all calls to it are guaranteed of getting the same values.
|
||
!--
|
||
|
||
DIX$def_cons =
|
||
%EXPAND DIX$def_con('rounded', 'rnded', sts$k_info,
|
||
'Result is rounded')
|
||
%EXPAND DIX$def_con ('toobig', 'toobig', sts$k_severe,
|
||
'Converted source field too large for destination field')
|
||
%EXPAND DIX$def_con ('invdattyp', 'dattyp', sts$k_severe,
|
||
'Invalid data type code')
|
||
%EXPAND DIX$def_con ('unkargtyp', 'argtyp', sts$k_severe,
|
||
'Argument passed by descriptor is unknown type')
|
||
%EXPAND DIX$def_con ('unksys', 'unksys', sts$k_severe,
|
||
'Unknown system of origin specified')
|
||
%EXPAND DIX$def_con ('invlng', 'invlng', sts$k_severe,
|
||
'Length invalid or unspecified')
|
||
%EXPAND DIX$def_con ('invscal', 'invscl', sts$k_severe,
|
||
'Scale factor invalid or unspecified')
|
||
%EXPAND DIX$def_con ('graphic', 'graphc', sts$k_warning,
|
||
'Graphic character changed in conversion')
|
||
%EXPAND DIX$def_con ('fmtlost', 'fmtlst', sts$k_warning,
|
||
'Format effector gained or lost in conversion')
|
||
%EXPAND DIX$def_con ('nonprint', 'nonprn', sts$k_warning,
|
||
'Non-printing character gained or lost in conversion')
|
||
%EXPAND DIX$def_con ('trunc', 'trunc', sts$k_info,
|
||
'String too long for destination -- truncated')
|
||
%EXPAND DIX$def_con ('unimp', 'unimp', sts$k_severe,
|
||
'Unimplemented conversion')
|
||
%EXPAND DIX$def_con ('invalchar', 'invchr', sts$k_error,
|
||
'Invalid character in source field or conversion table')
|
||
%EXPAND DIX$def_con ('align', 'align', sts$k_severe,
|
||
'Invalid alignment for data type')
|
||
%EXPAND DIX$def_con ('unnorm', 'unnorm', sts$k_severe,
|
||
'Floating point number improperly normalized')
|
||
%EXPAND DIX$def_con ('impossible', 'imposs', sts$k_severe,
|
||
'Severe internal error') ! [%O'26']
|
||
%EXPAND DIX$def_con ('unsigned', 'unsign', sts$k_error,
|
||
'Negative value moved to unsigned field')
|
||
%EXPAND dix$def_con ('invbytsiz', 'bytsiz', sts$k_severe,
|
||
'Invalid byte size specified')
|
||
%EXPAND dix$def_con ('invdnumchr','dnmchr',sts$k_severe,
|
||
'Invalid source display numeric character')
|
||
%EXPAND dix$def_con ('invdnumsgn','dnmsgn',sts$k_severe,
|
||
'Invalid source display numeric sign character')
|
||
%EXPAND dix$def_con ('invpddgt', 'pddgt', sts$k_severe,
|
||
'Invalid source packed decimal digit')
|
||
%EXPAND dix$def_con ('invpdsgn', 'pdsgn', sts$k_severe,
|
||
'Invalid source packed decimal sign')
|
||
%, ! End DIX$def_cons definition
|
||
!++
|
||
! .hl 2 Literals for status codes
|
||
! Now that DIX$def_cons is defined, we can construct the
|
||
! literals for the status codes by creating a local definition of
|
||
! >cond_dat (which is undeclared after use) and expanding
|
||
! DIX$def_cons.
|
||
!
|
||
! [5] In BLISS32, the literals declared are external literal declarations.
|
||
! The actual message definitions come from the >DIX.MSG file, produced
|
||
! by the >dixmsg program from the other info in def_cons.
|
||
!--
|
||
cond_dat (cond_nam, fort_pseud, cond_value, cond_msg_txt) = ! \.P;>\
|
||
cond_nam %BLISS36 ( = cond_value) , %; ! [5]
|
||
|
||
%BLISS32 (EXTERNAL) LITERAL ! [5]
|
||
dix$def_cons ! Expand above cond_dat for each dix$def_con
|
||
! call above, thus defining literals for
|
||
! all conditions
|
||
dix$$foo %BLISS36 ( = 0) ; ! [5]
|
||
|
||
LITERAL ! [5]
|
||
max_condition = %NUMBER (cnd_seq),
|
||
dix_max_cond = %NUMBER (cnd_seq);
|
||
|
||
UNDECLARE ! This stuff is too wierd for the public
|
||
cnd_seq,
|
||
dix$$foo, ! [5]
|
||
%QUOTE cond_dat,
|
||
%QUOTE dix$def_con;
|
||
|
||
%SBTTL 'Macros for data type declarations'
|
||
|
||
!++
|
||
! .hl 1 Macros for data type declaration
|
||
!
|
||
! All the information about each data type will be embedded in a macro
|
||
! declaration below.
|
||
!
|
||
! A macro called >dt_class_`<class name`>_def will be defined for each
|
||
! class which, when expanded, calls the locally-defined macro
|
||
! >decl_`<class name`>_item once for each data item in the class,
|
||
! passing all the information provided in the initial definition.
|
||
!
|
||
! This approach centralizes all the data type characteristics in a
|
||
! single place, making them easy to change and to find.
|
||
!
|
||
! There are some special macros used here to set up the macros
|
||
! described above. First, an example:
|
||
! .s 1
|
||
! .index declare_class
|
||
! .index dt_class
|
||
! .index dt_code
|
||
! .index data_type
|
||
! .index end_class
|
||
! .index dix$k_max_class
|
||
! .index dt_class_`<name`>_max
|
||
! .index dt_`<name`>
|
||
! .literal
|
||
! COMPILETIME
|
||
! dt_class = 0,
|
||
! dt_code = 0;
|
||
!
|
||
! declare_class (class_name);
|
||
! %EXPAND data_type (type_name, short_name);
|
||
! .
|
||
! .
|
||
! .
|
||
! %EXPAND end_class;
|
||
! declare_class (class_name);
|
||
! %EXPAND data_type (type_name, short_name);
|
||
! .
|
||
! .
|
||
! .
|
||
! %EXPAND end_class;
|
||
! .
|
||
! .
|
||
! .
|
||
!
|
||
! This produces the following literal declarations:
|
||
! DT_class Class number for each class
|
||
! DT_CLASS_class_MAX Max data type code assigned in that class
|
||
! (min is always 1)
|
||
! DIX$K_MAX_CLASS Highest class code assigned
|
||
!
|
||
! It also declares the macro DT_CLASS_class_DEF, described below.
|
||
!
|
||
! Then, when you want to build a table (or whatever) based on the
|
||
! information you gave for each data type:
|
||
!
|
||
! MACRO
|
||
! DECL_class_name_ITEM (class_code, item_name, short_name, type_code,
|
||
! user_specified ...) =
|
||
! Appropriate_code; %;
|
||
!
|
||
! DT_CLASS_class_name_DEF;
|
||
! .end literal
|
||
!--
|
||
|
||
MACRO
|
||
!++
|
||
! .hl 2 >declare_class macro
|
||
! Call the declare_class macro at the start of the list of
|
||
! items for each class:
|
||
!--
|
||
|
||
!++ NO
|
||
! ; The MACRO declare_class basically does the following:
|
||
! ; 1) Define the MACRO current_class (which is undeclared
|
||
! ; in the MACRO end_class.
|
||
! ; 2) %ASSIGN dt_code = 0.
|
||
! ; 3) %ASSIGN dt_class = dt_class + 1.
|
||
! ; 4) Define the LITERAL dt_<class_name> = dt_class.
|
||
! ; 5) Define the MACRO dt_class_<class_name>_def. This is a little
|
||
! ; unusual because the definition is left open-ended. The MACRO
|
||
! ; declare_class is defined such that it expands to the following
|
||
! ; definition of dt_class_<class_name>_def ==>
|
||
! ;
|
||
! ; MACRO %NAME ('dt_class', class_name, '_def') =
|
||
! ; %, ! End declare_class
|
||
! ; This means that when declare_class is invoked, the call must be
|
||
! ; followed by the code that the user wishes to be the body of the
|
||
! ; MACRO dt_class_<class_name>_def.
|
||
! ;
|
||
!--
|
||
|
||
declare_class (class_name) = ! \ .p;>\
|
||
|
||
MACRO
|
||
current_class =
|
||
class_name %QUOTE %;
|
||
|
||
%ASSIGN (dt_code, 0) ! Initialize type code
|
||
%ASSIGN (dt_class, dt_class + 1)
|
||
|
||
LITERAL
|
||
%NAME ('dt_', class_name) = %NUMBER (dt_class);
|
||
|
||
!
|
||
! ; At compile time, prints the number assigned to this class.
|
||
!
|
||
%PRINT (%NAME ('dt_', class_name), '=', %NUMBER (%NAME ('dt_', class_name)))
|
||
|
||
! Define the name of the MACRO whose body directly follows the call
|
||
! to declare_class (class_name). The name is built using the parameter
|
||
! "class_name" and is the following: dt_class_<class_name>_def.
|
||
! NOTE: The body of this MACRO does not appear here, but rather
|
||
! appears in the code directly after the call to declare_class.
|
||
|
||
MACRO
|
||
%NAME ('dt_class_', class_name, '_def') =
|
||
%, ! End declare_class
|
||
!++
|
||
! .hl 2 >data_type
|
||
! The data_type macro is used to declare a specific data type
|
||
! within a class declaration. It assigns the within-class type
|
||
! code from compiletime variable >dt_code>, which is incremented.
|
||
!--
|
||
data_type (item_name, short_name) = ! \.P;>\
|
||
%QUOTE %EXPAND %ASSIGN (dt_code, dt_code + 1)
|
||
!++
|
||
! Expansion calls macro >decl_`<class name`>_item (which the user
|
||
! must define) to do whatever is wanted for each item in the class.
|
||
!--
|
||
%QUOTE %EXPAND %NAME ('decl_', current_class, '_item') ! Name of macro to invoke
|
||
( ! MACRO-actuals enclosed
|
||
%QUOTE %EXPAND %NAME ('dt_', current_class), ! MACRO actual
|
||
item_name, ! Macro actual
|
||
short_name, ! Macro actual
|
||
%QUOTE %EXPAND %NUMBER(dt_code), ! Macro actual
|
||
%QUOTE %EXPAND %REMAINING ! Macro actual
|
||
) ! End of MACRO-actuals
|
||
!
|
||
! ; At compile-time, data_type prints the within-class code assigned
|
||
! ; to each data type.
|
||
!
|
||
%QUOTE %EXPAND %PRINT !
|
||
( ! %PRINT actuals enclosed
|
||
item_name, ! %PRINT actual
|
||
' type code=', ! %PRINT actual
|
||
%QUOTE %EXPAND %NUMBER(dt_code) ! %PRINT actual
|
||
) ! End %PRINT actuals
|
||
%, ! End data_type definition
|
||
!++
|
||
! .hl 2 >end_class
|
||
! The macro end_class handles termination of the declarations for a
|
||
! class of data items.
|
||
!--
|
||
end_class =
|
||
%QUOTE %;
|
||
|
||
LITERAL ! ; The literal >dt_class_`<name`>_max> is
|
||
! ; defined as the maximum code in the class.
|
||
%QUOTE %EXPAND %NAME
|
||
( ! %NAME actuals enclosed
|
||
'dt_class_', ! %NAME actual
|
||
current_class, ! %NAME actual
|
||
'_max' ! %NAME actual
|
||
) ! End %NAME actuals
|
||
= !
|
||
%QUOTE %EXPAND %NUMBER (dt_code);
|
||
!
|
||
! ; At compile-time, print the max code in the class from the
|
||
! ; literal just defined.
|
||
!
|
||
%QUOTE %EXPAND %PRINT ( ! Begin actuals to %PRINT
|
||
%QUOTE %EXPAND %NAME ! Actual to %PRINT
|
||
( ! Begin actuals to %NAME
|
||
'dt_class_', ! Actual to %NAME
|
||
current_class, ! Actual to %NAME
|
||
'_max' ! Actual to %NAME
|
||
), ! End actuals to %NAME
|
||
'=', ! Actual to %PRINT
|
||
%QUOTE %EXPAND %NUMBER ! Actual to %PRINT
|
||
( ! Begin actuals to %NUMBER
|
||
%QUOTE %EXPAND %NAME ! Actual to %NUMBER
|
||
( ! Begin actuals to %NAME
|
||
'dt_class_', ! Actual to %NAME
|
||
current_class, ! Actual to %NAME
|
||
'_max' ! Actual to %NAME
|
||
) ! End of actuals to %NAME
|
||
) ! End of actuals to %NUMBER
|
||
) ! End of actuals to %PRINT
|
||
UNDECLARE ! Get rid of one-shot variables
|
||
%QUOTE %QUOTE current_class;
|
||
%; ! End definition of end_class
|
||
|
||
%SBTTL 'Data type definitions'
|
||
|
||
!++
|
||
! .hl 1 Data type definitions
|
||
!
|
||
! The characteristics of all data types in all classes will be defined
|
||
! here.
|
||
!
|
||
! The resulting information will be stored mostly as macro
|
||
! definitions (described above) and will be expanded into tables as
|
||
! necessary in the general and type-specific conversion modules.
|
||
!--
|
||
|
||
COMPILETIME
|
||
dt_class = 0,
|
||
dt_code = 0;
|
||
|
||
%sbttl 'Class String data type definitions'
|
||
!++
|
||
! .hl 2 Class string
|
||
! .index class string
|
||
!
|
||
! Information to be provided for each data type:
|
||
! .list 1, "o"
|
||
! .le;Name as quoted string
|
||
! .le;Short name as quoted string
|
||
! .le;Byte size
|
||
! .le;System of origin
|
||
! .le;Length indicating technique (value indicating whether a length must
|
||
! be given or if a null length is expected)
|
||
! .le;Name of character set as quoted string. Since the build_cst macro
|
||
! (defined and used in DIXSTR) names everything consistently based on
|
||
! the character set name, this is all that is needed to find everything.
|
||
! .le;Fill character to use (numeric)
|
||
! .le;Character to substitute if no matching char in set (numeric)
|
||
! .end list
|
||
!--
|
||
|
||
!
|
||
! ; Names for methods of indicating length:
|
||
! ;.list 0, "o"
|
||
|
||
$literal
|
||
std$k_lng_spec = $distinct, ! \.le;>\
|
||
std$k_lng_nul = $distinct, ! \.le;>\
|
||
std$k_lng_ult = $distinct; ! \.le;>\
|
||
|
||
LITERAL
|
||
std$k_max_lng_indic = %NUMBER (std$k_lng_ult) - 1 ; !\.le;>\
|
||
|
||
! ;.end list
|
||
|
||
UNDECLARE std$k_lng_ult;
|
||
|
||
declare_class ('string') ! call declare_class
|
||
!
|
||
! The code following the call to declare_class is actually the body of the
|
||
! MACRO dt_class_string_def.
|
||
!
|
||
%EXPAND
|
||
data_type ('ASCII_7', 'ASCII7', 7, sys_lcg, std$k_lng_spec, 'ascii', 32, 92)
|
||
%EXPAND
|
||
data_type ('ASCII_8', 'ASCII8', 8, sys_8bit, std$k_lng_spec, 'ascii', 32, 92)
|
||
%EXPAND
|
||
data_type ('ASCIZ', 'ASCIZ', 7, sys_lcg, std$k_lng_nul, 'ascii', 0, 92)
|
||
%EXPAND
|
||
data_type ('EBCDIC_8', 'EBCDC8', 8, sys_8bit, std$k_lng_spec, 'ebcdic', 64, 224)
|
||
%EXPAND
|
||
data_type ('EBCDIC_9', 'EBCDC9', 9, sys_lcg, std$k_lng_spec, 'ebcdic', 64, 224)
|
||
%EXPAND
|
||
data_type ('SIXBIT', 'SIXBIT', 6, sys_lcg, std$k_lng_spec, 'sixbit', 0, 60)
|
||
!
|
||
%EXPAND
|
||
end_class
|
||
|
||
%SBTTL 'String data table (STD)'
|
||
|
||
!++
|
||
! .hl 3 String data table (>std>)
|
||
! Format for the alphanumeric string data table.
|
||
! This table is indexed by data subtype (within its class).
|
||
! .literal
|
||
!--
|
||
|
||
$field
|
||
std_fields =
|
||
SET
|
||
!++ copy
|
||
std$v_byt_siz = [$bits (6)], ! Byte size of string
|
||
std$v_sys_orig = [$bits (3)], ! Code for system of origin
|
||
std$v_lng_indic = [$bits (2)] ! Length indication
|
||
! (values std$k_lng_<something> defined above)
|
||
!-- .end literal
|
||
|
||
TES;
|
||
|
||
LITERAL
|
||
std$k_size = $field_set_size;
|
||
|
||
!++
|
||
! To declare a data segment to be of type std, use the macro dtt_st
|
||
! in place of the structure and field attributes in the data item
|
||
! declaration.
|
||
!--
|
||
|
||
MACRO
|
||
dtt_st = BLOCKVECTOR [dt_class_string_max + 1, std$k_size] FIELD (std_fields) % ;
|
||
%sbttl 'Class fixed binary data type definitions'
|
||
|
||
!++
|
||
! .hl 2 Class fixed binary
|
||
!
|
||
! Information to be provided for each data type:
|
||
!
|
||
! .list 1
|
||
! .le;Name as quoted string
|
||
! .le;Short name as quoted string
|
||
! .le;Fixed or variable length (use literals)
|
||
! .le;Signed or unsigned (use literals)
|
||
! .le;Minimum length if variable (unsigned) (zero if not variable)
|
||
! .le;Maximum length if variable (unsigned)
|
||
! .le;Minimum scale factor (signed)
|
||
! .le;Maximum scale factor (signed)
|
||
! .le;Program for BPM/BIM
|
||
! .end list
|
||
!--
|
||
|
||
!++
|
||
! Literals for specifying above parameters:
|
||
! .list 0, "o"
|
||
!--
|
||
|
||
LITERAL
|
||
fbd$k_lng_fixed = 1, ! \.le;\ Type is fixed-length
|
||
fbd$k_lng_variable = 2, ! \.le;\ Type is variable-length
|
||
fbd$k_signed = 3, ! \.le;\ Type is signed
|
||
fbd$k_unsigned = 4; ! \.le;\ Type is unsigned
|
||
! ; .end list
|
||
|
||
!++
|
||
! .hl 3 Binary pseudo-machine (BPM)
|
||
! .index pseudo-machine BPM
|
||
! .index binary pseudo-machine BPM
|
||
! .index bpm
|
||
! Define the pseudo-machine to run (in different directions) in the
|
||
! routines that convert FB to CB and vs.
|
||
!
|
||
! Each pseudo-instruction has an op code and two signed integer (small)
|
||
! operands. The structure to represent a single instruction is defined as a
|
||
! block with the following fields:
|
||
!--
|
||
|
||
$field ! ; .s 1.list 0, "o"
|
||
bpm_fields =
|
||
SET
|
||
!++ copy /strip .le;>
|
||
bpm$v_opcode = [$byte], ! Op code is this size for VAX alignment
|
||
bpm$v_op_1 = [$tiny_integer], ! Must be signed, at least +/- 128
|
||
bpm$v_op_2 = [$tiny_integer] ! Must be signed, at least +/- 128
|
||
!-- .end list
|
||
TES;
|
||
LITERAL
|
||
bpm$k_size = $field_set_size,
|
||
bpm$b_opcode = 0, ! OFFSET
|
||
bpm$s_opcode = %BLISS36 (9) %BLISS32 (8), ! Size of field
|
||
bpm$b_op_1 = %BLISS36 (9) %BLISS32 (8), ! These fields depend on the
|
||
bpm$s_op_1 = %BLISS36 (9) %BLISS32 (8), ! way XPORT processes the
|
||
bpm$b_op_2 = %BLISS36 (18) %BLISS32 (16), ! definitions above!!!
|
||
bpm$s_op_2 = %BLISS36 (9) %BLISS32 (8); ! Watch out!!!
|
||
|
||
!++
|
||
! The op-codes for the pseudo-machine are as follows:
|
||
!--
|
||
$literal ! ; .s 1.list 1
|
||
!++ copy /strip .le;>
|
||
bpm$k_op_move = $distinct, ! Move contiguous bits
|
||
bpm$k_op_move_var = $distinct, ! Move contiguous bits with variable length
|
||
bpm$k_op_sign = $distinct, ! Process sign
|
||
bpm$k_op_sign_var = $distinct, ! Process sign in variable length
|
||
bpm$k_op_done = $distinct; ! Do cleanup and terminate.
|
||
!--
|
||
! ; Must be last in list!!
|
||
! ; .END LIST
|
||
|
||
LITERAL
|
||
bpm$k_op_max = bpm$k_op_done - 1; ! \.p;Largest bpm opcode is \
|
||
|
||
!++
|
||
! .hl 3 Building BPM instructions
|
||
! Macros to build pseudo-machine instructions:
|
||
!--
|
||
|
||
MACRO
|
||
bpm_any ! \.hl 4 \
|
||
!++
|
||
! builds any pseudo-machine instruction.
|
||
!
|
||
! Formal arguments:
|
||
!--
|
||
( ! ; .list 1
|
||
op_code, ! \.le;\: opcode for instruction
|
||
op_1, ! \.le;\: signed value for first op
|
||
op_2 ! \.le;\: signed value for second op
|
||
) = ! ; .end list
|
||
op_code OR
|
||
(op_1 AND (1^bpm$s_op_1 - 1))^bpm$b_op_1 OR
|
||
(op_2 AND (1^bpm$s_op_2 - 1))^bpm$b_op_2 %,
|
||
bpm_move ! \.hl 4\
|
||
!++
|
||
! builds the pseudo-machine instruction to move continuous bits
|
||
! between FB and CB fields.
|
||
!
|
||
! Formal arguments:
|
||
!--
|
||
( ! ; .list 1
|
||
Offset, ! \.le;\: from LO bit of FB
|
||
length ! \.le;\: number of bits to move
|
||
) = ! ; .end list
|
||
bpm_any (bpm$k_op_move, offset, length) %,
|
||
bpm_move_var ! \.hl 4\
|
||
!++
|
||
! builds the pseudo-machine instruction to move continuous bits
|
||
! between FB and CB variable length fields.
|
||
!
|
||
! Formal arguments:
|
||
!--
|
||
( ! ; .list 1
|
||
Offset, ! \.le;\: from LO bit of FB
|
||
length ! \.le;\: number of bits to move - length
|
||
) = ! ; .end list
|
||
bpm_any (bpm$k_op_move_var, offset, length) %,
|
||
bpm_sign ! \.hl 4\
|
||
!++
|
||
! builds the pseudo-machine instruction to move sign information
|
||
! between FB and CB fields.
|
||
!
|
||
! Formal arguments:
|
||
!--
|
||
( ! ; .list 1
|
||
Offset ! \.le;\: from LO bit of FB
|
||
) = ! ; .end list
|
||
bpm_any (bpm$k_op_sign, offset, 0) %,
|
||
bpm_sign_var ! \.hl 4\
|
||
!++
|
||
! builds the pseudo-machine instruction to move sign information
|
||
! between FB and CB variable length fields.
|
||
!
|
||
! Formal arguments:
|
||
!--
|
||
( ! ; .list 1
|
||
Offset ! \.le;\: from LO bit of FB - length
|
||
) = ! ; .end list
|
||
bpm_any (bpm$k_op_sign_var, offset, 0) %,
|
||
bpm_done ! \.hl 4\
|
||
!++
|
||
! builds the pseudo-machine instruction to terminate a pseudo-program.
|
||
!
|
||
! Formal arguments: none.
|
||
!--
|
||
=
|
||
bpm_any (bpm$k_op_done, 0, 0) % ;
|
||
|
||
!
|
||
! And now, the real class fixed binary definitions in terms of this glop.
|
||
!
|
||
|
||
declare_class ('fbin') ! call declare_class
|
||
!
|
||
! The code following the call to declare_class is actually the body of the
|
||
! MACRO dt_class_fbin_def.
|
||
!
|
||
%EXPAND data_type ('SBF128', 'SBF128', fbd$k_lng_fixed, fbd$k_signed,0,0,0,0,
|
||
(bpm_move (0, 127), bpm_sign (127), bpm_done), 128, 127)
|
||
%EXPAND data_type ('SBF16', 'SBF16', fbd$k_lng_fixed, fbd$k_signed,0,0,-18,18,
|
||
(bpm_move (0, 15), bpm_sign (15), bpm_done), 16, 15)
|
||
%EXPAND data_type ('SBF32', 'SBF32', fbd$k_lng_fixed, fbd$k_signed,0,0,-18,18,
|
||
(bpm_move (0, 31), bpm_sign (31), bpm_done), 32, 31)
|
||
%EXPAND data_type ('SBF36', 'SBF36', fbd$k_lng_fixed, fbd$k_signed,0,0,-18,18,
|
||
(bpm_move (0, 35), bpm_sign (35), bpm_done), 36, 35)
|
||
%EXPAND data_type ('SBF48', 'SBF48', fbd$k_lng_fixed, fbd$k_signed,0,0,0,0,
|
||
(bpm_move (0, 47), bpm_sign (47), bpm_done), 48, 47)
|
||
%EXPAND data_type ('SBF64', 'SBF64', fbd$k_lng_fixed, fbd$k_signed,0,0,-18,18,
|
||
(bpm_move (0, 63), bpm_sign (63), bpm_done), 64, 63)
|
||
%EXPAND data_type ('SBF72', 'SBF72', fbd$k_lng_fixed, fbd$k_signed,0,0,-18,18,
|
||
(bpm_move (0, 35), bpm_move (-36, 35), bpm_sign (-1), bpm_done), 72, 70)
|
||
%EXPAND data_type ('SBF8', 'SBF8', fbd$k_lng_fixed, fbd$k_signed,0,0,0,0,
|
||
(bpm_move (0, 7), bpm_sign (7), bpm_done), 8, 7)
|
||
%EXPAND data_type ('SBFVAR', 'SBFVAR', fbd$k_lng_variable, fbd$k_signed,0,36,0,0,
|
||
(bpm_move_var (0, -1), bpm_sign_var (-1), bpm_done), 0, 0)
|
||
%EXPAND data_type ('UBF16', 'UBF16', fbd$k_lng_fixed, fbd$k_unsigned,0,0,0,0,
|
||
(bpm_move (0, 16), bpm_done), 16, 16)
|
||
%EXPAND data_type ('UBF32', 'UBF32', fbd$k_lng_fixed, fbd$k_unsigned,0,0,0,0,
|
||
(bpm_move (0, 32), bpm_done), 32, 32)
|
||
%EXPAND data_type ('UBF8', 'UBF8', fbd$k_lng_fixed, fbd$k_unsigned,0,0,0,0,
|
||
(bpm_move (0, 8), bpm_done), 8, 8)
|
||
%EXPAND data_type ('UBFVAR', 'UBFVAR', fbd$k_lng_variable, fbd$k_unsigned,0,36,0,0,
|
||
(bpm_move_var (0, 0), bpm_done), 0, 0)
|
||
! UBF128 is new for DIL V2.1
|
||
%EXPAND data_type ('UBF128', 'UBF128', fbd$k_lng_fixed, fbd$k_unsigned,0,0,-18,18,
|
||
(bpm_move (0, 128), bpm_done), 128, 128)
|
||
! UBF36 is new for DIL V2.1
|
||
%EXPAND data_type ('UBF36', 'UBF36', fbd$k_lng_fixed, fbd$k_unsigned,0,0,-18,18,
|
||
(bpm_move (0, 36), bpm_done), 36, 36)
|
||
! UBF64 is new for DIL V2.1
|
||
%EXPAND data_type ('UBF64', 'UBF64', fbd$k_lng_fixed, fbd$k_unsigned,0,0,-18,18,
|
||
(bpm_move (0, 64), bpm_done), 64, 64)
|
||
! UBF72 is new for DIL V2.1
|
||
%EXPAND data_type ('UBF72', 'UBF72', fbd$k_lng_fixed, fbd$k_unsigned,0,0,-18,18,
|
||
(bpm_move (0, 36), bpm_move (-36, 36), bpm_done), 72, 72)
|
||
|
||
%EXPAND end_class
|
||
|
||
%sbttl 'Fixed Binary data table (FBD)'
|
||
|
||
!++
|
||
! .hl 3 Fixed binary data table (>fbd>)
|
||
! Format for the fixed binary data table. This table is indexed by
|
||
! data subtype (within class).
|
||
! .s 1
|
||
! .literal
|
||
!--
|
||
$field
|
||
fbd_fields =
|
||
SET
|
||
!++ copy
|
||
fbd$v_bpm_program = [$address], ! Address of BPM program
|
||
! These two bits occupy HO part of word on 36-bit
|
||
fbd$v_signed = [$bit], ! Bit set if field is signed
|
||
fbd$v_variable = [$bit], ! Bit set if field length variable
|
||
$align (byte) ! Align remaining fields
|
||
fbd$v_min_lng = [$byte], ! Minimum length (unsigned field)
|
||
fbd$v_max_lng = [$byte], ! Maximum length (unsigned)
|
||
fbd$v_min_scale = [$tiny_integer], ! Signed minimum scale
|
||
fbd$v_max_scale = [$tiny_integer], ! Signed maximum scale
|
||
fbd$v_siz = [$byte], ! fld size in bits (necessary for DIU)
|
||
fbd$v_signif_bits = [$byte] ! for unsigned integers = # of bits used,
|
||
! for signed integers = # of significant bits (necessary for DIU)
|
||
|
||
!-- .end literal
|
||
TES;
|
||
|
||
LITERAL
|
||
fbd$k_size = $field_set_size;
|
||
|
||
MACRO
|
||
dtt_fbin ! \.p;Macro >\
|
||
!++
|
||
! declares an item to have the right structure and field attributes for
|
||
! the fixed binary data table.
|
||
!--
|
||
= BLOCKVECTOR [dt_class_fbin_max + 1, fbd$k_size] FIELD (fbd_fields) % ;
|
||
%SBTTL 'Class floating point data type definitions'
|
||
|
||
!++
|
||
! .hl 2 Class floating point
|
||
!
|
||
! Information to be provided for each data type:
|
||
!
|
||
! .list 1
|
||
! .le;Name as quoted string
|
||
! .le;Short name as quoted string
|
||
! .le;Representation (use literals)
|
||
! .le;Exponent offset
|
||
! .le;Number of significant bits in mantissa (including hidden high-order
|
||
! bit if there is one)
|
||
! .le;Program for FPM/FIM
|
||
! .end list
|
||
!
|
||
! Literals for specifying above:
|
||
! .list 0, "o"
|
||
!--
|
||
|
||
$literal
|
||
!++ copy /strip .le;
|
||
fpd$k_lcg = $distinct, ! Number is in LCG representation
|
||
fpd$k_vax = $distinct, ! Number is in VAX/PDP-11 representation
|
||
fpd$k_rep_ult = $distinct;
|
||
!-- .end list
|
||
|
||
LITERAL
|
||
fpd$k_rep_max = fpd$k_rep_ult - 1; ! \.p;Max representation value is \
|
||
|
||
UNDECLARE
|
||
fpd$k_rep_ult;
|
||
|
||
! Literals for complex/simple floating point types
|
||
$LITERAL fpd$k_complex = $DISTINCT,
|
||
fpd$k_simple = $DISTINCT,
|
||
fpd$k_typ_ult = $DISTINCT;
|
||
|
||
LITERAL fpd$k_typ_max = fpd$k_typ_ult - 1;
|
||
|
||
UNDECLARE fpd$k_typ_ult;
|
||
|
||
!++
|
||
! .hl 3 Floating point pseudo-machine FPM
|
||
! .index pseudo-machine FPM
|
||
! .index floating point pseudo-machine FPM
|
||
! .index fpm
|
||
!
|
||
! Define the pseudo-machine used to convert fp to cf and vs (the programs
|
||
! are also run to convert cf to fp; of course the interpretation
|
||
! of the instructions changes).
|
||
!
|
||
! Each instruction has an op code and two signed small integer operands.
|
||
! The structure to represent a single instruction is defined as a block with
|
||
! the following fields:
|
||
!--
|
||
|
||
$field
|
||
fpm_fields = ! ; .s 1 .list 0, "o"
|
||
SET
|
||
!++ copy /strip .le;>
|
||
fpm$v_opcode = [$byte], ! Op code is large for alignment on vax
|
||
fpm$v_op_1 = [$tiny_integer], ! Must be signed, +/- 128
|
||
fpm$v_op_2 = [$tiny_integer] ! Must be signed, +/- 128
|
||
!-- .end list
|
||
TES;
|
||
|
||
LITERAL
|
||
fpm$k_size = $field_set_size,
|
||
!++
|
||
! Create names for bit positions of above fields. These definitions depend
|
||
! on how XPORT process the above stuff, so be extremely careful whem
|
||
! mucking about with either one!!!
|
||
!--
|
||
|
||
!++ copy /strip .i 5;
|
||
fpm$b_opcode = 0, ! Offset
|
||
fpm$s_opcode = %BLISS36 (9) %BLISS32 (8), ! Size of field
|
||
fpm$b_op_1 = %BLISS36 (9) %BLISS32 (8),
|
||
fpm$s_op_1 = %BLISS36 (9) %BLISS32 (8),
|
||
fpm$b_op_2 = %BLISS36 (18) %BLISS32 (16),
|
||
fpm$s_op_2 = %BLISS36 (9) %BLISS32 (8);
|
||
!--
|
||
|
||
!++
|
||
! Op-codes for the FPM:
|
||
!--
|
||
$literal ! ;.list 1
|
||
!++ copy /strip .le;>
|
||
fpm$k_op_sign = $distinct, ! Set sign to pos or neg
|
||
fpm$k_op_exp = $distinct, ! Move exponent bits
|
||
fpm$k_op_mant = $distinct, ! Move mantissa bits
|
||
fpm$k_op_mant1 = $distinct, ! Create hidden leading mantissa bit
|
||
fpm$k_op_done = $distinct; ! Do cleanup and terminate.
|
||
!--
|
||
! ; "done" must be last!!!
|
||
! ; .end list
|
||
|
||
!++
|
||
! .hl 3 Building FPM instructions
|
||
! Macros to build pseudo-machine instructions:
|
||
!--
|
||
|
||
MACRO
|
||
fpm_any ! \.hl 4 \
|
||
!++
|
||
! builds any pseudo-machine instruction.
|
||
!
|
||
! Formal arguments:
|
||
!--
|
||
( ! ; .list 1
|
||
op_code, ! \.le;\: opcode for instruction
|
||
op_1, ! \.le;\: signed value for first op
|
||
op_2 ! \.le;\: signed value for second op
|
||
) = ! ; .end list
|
||
op_code OR
|
||
(op_1 AND (1^fpm$s_op_1 - 1))^fpm$b_op_1 OR
|
||
(op_2 AND (1^fpm$s_op_2 - 1))^fpm$b_op_2 %,
|
||
|
||
fpm_sign ! \.hl 4\
|
||
!++
|
||
! builds the pseudo-machine instruction to set the CF sign to positive or
|
||
! negative (zero is handled in the done routine).
|
||
!
|
||
! Formal arguments:
|
||
!--
|
||
( ! ;.s 1.list 1
|
||
offset ! \.le;\: Offset from low order bit of FP
|
||
) = ! ;.end list
|
||
fpm_any (fpm$k_op_sign, offset, 0) % ,
|
||
fpm_exp ! \.hl 4\
|
||
!++
|
||
! builds the pseudo-machine instruction to move exponent bits.
|
||
! Exponent bits are moved from low order to high order. No sign
|
||
! extension is done -- this must be handled by the done routine.
|
||
! This instruction may only be called once -- segmented exponents
|
||
! are not supported. Exponents larger than a fullword are not
|
||
! supported.
|
||
!
|
||
! Formal arguments:
|
||
!--
|
||
( ! ;.s 1.list 1
|
||
offset, ! \.le;\: Offset from low order bit of FP
|
||
length ! \.le;\: Number of bits to move
|
||
) = ! ;.end list
|
||
fpm_any (fpm$k_op_exp, offset, length) % ,
|
||
fpm_mant ! \.hl 4\
|
||
!++
|
||
! builds the psedo-machine instruction to move mantissa bits.
|
||
!
|
||
! Mantissa bits are moved from high order to low order. Therefore
|
||
! the offset specified is to the highest-order bit to be moved.
|
||
!
|
||
! This instruction may be used several times to move non-contiguous
|
||
! mantissa fields.
|
||
!
|
||
! Formal arguments:
|
||
!--
|
||
( ! ;.s 1.list 1
|
||
offset, ! \.le;\: Offset from LO bit of FP
|
||
! ; to HO bit to move.
|
||
length ! \.le;\: Number of bits to move
|
||
! ; (lower-order bits).
|
||
) = ! ;.end list
|
||
fpm_any (fpm$k_op_mant, offset, length) % ,
|
||
fpm_mant1 ! \.hl 4\
|
||
!++
|
||
! builds the instruction for creating the leading mantissa bit, which is
|
||
! not represented in some implementations.
|
||
!
|
||
! Formal arguments: None
|
||
!--
|
||
=
|
||
fpm_any (fpm$k_op_mant1, 0, 0) % ,
|
||
fpm_done ! \.hl 4\
|
||
!++
|
||
! builds the done instruction. This terminates processing of the
|
||
! pseudo-program and executes the final cleanup routine.
|
||
!
|
||
! The final cleanup routine transforms the broken-down bit fields made
|
||
! by the simple moves of the other instructions into the true canonical
|
||
! form.
|
||
!
|
||
! Formal arguments: None.
|
||
!--
|
||
=
|
||
fpm_any (fpm$k_op_done, 0, 0) % ;
|
||
|
||
!
|
||
! And now, the real class floating point definitions in terms of this glop.
|
||
!
|
||
declare_class ('fp') ! call declare_class
|
||
!
|
||
! The code following the call to declare_class is actually the body of the
|
||
! MACRO dt_class_fp_def.
|
||
!
|
||
%EXPAND data_type ('D_FLOAT', 'DFLOAT', fpd$k_vax, 128, 56,
|
||
(fpm_sign (15), fpm_exp (7, 8), fpm_mant1, fpm_mant (6, 7),
|
||
fpm_mant (31, 16), fpm_mant (47, 16), fpm_mant (63, 16), fpm_done ), 64,
|
||
fpd$k_simple)
|
||
%EXPAND data_type ('F_FLOAT', 'FFLOAT', fpd$k_vax, 128, 24,
|
||
(fpm_sign (15), fpm_exp (7, 8), fpm_mant1, fpm_mant (6, 7),
|
||
fpm_mant (31, 16), fpm_done ), 32, fpd$k_simple)
|
||
%EXPAND data_type ('FLOAT_36', 'FLOT36', fpd$k_lcg, 128, 27,
|
||
(fpm_sign (35), fpm_exp (27, 8), fpm_mant (26, 27), fpm_done ), 36,
|
||
fpd$k_simple)
|
||
%EXPAND data_type ('FLOAT_72', 'FLOT72', fpd$k_lcg, 128, 62,
|
||
(fpm_sign (-1), fpm_exp (-9, 8), fpm_mant (-10, 27), fpm_mant (34, 35),
|
||
fpm_done ), 72, fpd$k_simple)
|
||
%EXPAND data_type ('G_FLOAT', 'GFLOAT', fpd$k_vax, 1024, 53,
|
||
(fpm_sign (15), fpm_exp (4, 11), fpm_mant1, fpm_mant (3, 4),
|
||
fpm_mant (31, 16), fpm_mant (47, 16), fpm_mant (63, 16), fpm_done ), 64,
|
||
fpd$k_simple)
|
||
%EXPAND data_type ('G_FLOAT72', 'GFLO72', fpd$k_lcg, 1024, 59,
|
||
(fpm_sign (-1), fpm_exp (-12, 11), fpm_mant (-13, 24), fpm_mant (34, 35),
|
||
fpm_done ), 72, fpd$k_simple)
|
||
%EXPAND data_type ('H_FLOAT', 'HFLOAT', fpd$k_vax, 16384, 113,
|
||
(fpm_sign (15), fpm_exp (0, 15), fpm_mant1, fpm_mant (31, 16),
|
||
fpm_mant (47, 16), fpm_mant (63, 16), fpm_mant (79, 16),
|
||
fpm_mant (95, 16), fpm_mant (111, 16), fpm_mant (127, 16), fpm_done ), 128,
|
||
fpd$k_simple)
|
||
%EXPAND data_type ('D_CMPLX', 'DCMPLX', fpd$k_vax, 128, 56,
|
||
(fpm_sign (15), fpm_exp (7, 8), fpm_mant1, fpm_mant (6, 7),
|
||
fpm_mant (31, 16), fpm_mant (47, 16), fpm_mant (63, 16), fpm_done ),
|
||
64, fpd$k_complex)
|
||
%EXPAND data_type ('F_CMPLX', 'FCMPLX', fpd$k_vax, 128, 24,
|
||
(fpm_sign (15), fpm_exp (7, 8), fpm_mant1, fpm_mant (6, 7),
|
||
fpm_mant (31, 16), fpm_done ), 32, fpd$k_complex)
|
||
%EXPAND data_type ('F_CMPLX36', 'FCMP36', fpd$k_lcg, 128, 27,
|
||
(fpm_sign (35), fpm_exp (27, 8), fpm_mant (26, 27), fpm_done ),
|
||
36, fpd$k_complex)
|
||
%EXPAND data_type ('G_CMPLX', 'GCMPLX', fpd$k_vax, 1024, 53,
|
||
(fpm_sign (15), fpm_exp (4, 11), fpm_mant1, fpm_mant (3, 4),
|
||
fpm_mant (31, 16), fpm_mant (47, 16), fpm_mant (63, 16), fpm_done ),
|
||
64, fpd$k_complex)
|
||
%EXPAND data_type ('H_CMPLX', 'HCMPLX', fpd$k_vax, 16384, 113,
|
||
(fpm_sign (15), fpm_exp (0, 15), fpm_mant1, fpm_mant (31, 16),
|
||
fpm_mant (47, 16), fpm_mant (63, 16), fpm_mant (79, 16),
|
||
fpm_mant (95, 16), fpm_mant (111, 16), fpm_mant (127, 16), fpm_done ),
|
||
128, fpd$k_complex)
|
||
|
||
%EXPAND end_class
|
||
|
||
%SBTTL 'Floating point data table'
|
||
|
||
!++
|
||
! .hl 3 Floating point data table (>fpd>)
|
||
! Format for the floating point data table. This table is indexed
|
||
! by the data subtype (within its class).
|
||
! .literal
|
||
!--
|
||
|
||
$field
|
||
fpd_fields =
|
||
SET
|
||
!++ COPY
|
||
fpd$v_fpm_program = [$address], ! Address of FPM program for type
|
||
fpd$v_representation = [$byte], ! Encodes details of representation
|
||
! within the 3 standard fields
|
||
fpd$v_exp_offset = [$bytes (2)], ! Unsigned offset to apply to exponent
|
||
fpd$v_mant_bits = [$byte], ! Unsigned number of significant bits in mantissa
|
||
fpd$v_siz = [$short_integer], ! fld size in bits (necessary for DIU)
|
||
fpd$v_typ = [$byte] ! code indicates simple or complex fp type (for DIU)
|
||
!-- .END LITERAL
|
||
TES;
|
||
|
||
LITERAL
|
||
fpd$k_size = $field_set_size;
|
||
|
||
MACRO
|
||
dtt_fp ! \.p;Macro >\
|
||
!++
|
||
! declares an item to have the right structure and field attributes for
|
||
! the floating point data table.
|
||
!--
|
||
= BLOCKVECTOR [dt_class_fp_max + 1, fpd$k_size] FIELD (fpd_fields) % ;
|
||
%SBTTL 'Class Display Numeric data type definitions'
|
||
!++
|
||
! .hl 2 Class Display Numeric
|
||
! .index class display numeric
|
||
!
|
||
! Information to be provided for each data type:
|
||
! .list 1, "o"
|
||
! .le;Name as quoted string
|
||
! .le;Short name as quoted string
|
||
! .le;Byte size
|
||
! .le;System of origin
|
||
! .le;code indicating sign type (use literals provided below)
|
||
! .le;Maximum length allowed
|
||
! .le;Character set used
|
||
! .le;Size of character set
|
||
! .end list
|
||
!--
|
||
|
||
! ; Literal names used to indicate different sign representations:
|
||
! ;.s1.list 0, "o"
|
||
|
||
LITERAL
|
||
dnd$k_unsigned = 0, ! \.le;>\ unsigned
|
||
dnd$k_lead_sep = 1, ! \.le;>\ signed/leading/separate
|
||
dnd$k_lead_over = 2, ! \.le;>\ signed/leading/overpunched
|
||
dnd$k_trail_sep = 3, ! \.le;>\ signed/trailing/separate
|
||
dnd$k_trail_over = 4; ! \.le;>\ signed/trailing/overpunched
|
||
|
||
! ;.end list
|
||
|
||
! ; Literals for display numeric character set reference codes:
|
||
|
||
LITERAL ! ;.s 1 .list 0, "o"
|
||
cs_ascii = 0, ! \.le;\ ascii char set
|
||
cs_asciix = 1, ! \.le;\ ascii extended char set
|
||
cs_ebcdic = 2, ! \.le;\ ebcdic char set
|
||
cs_sixbit = 3, ! \.le;\ sixbit char set
|
||
cs_max = 4; ! ;.end list
|
||
|
||
! ; Literals for display numeric character set sizes:
|
||
|
||
LITERAL ! ;.s 1 .list 0, "o"
|
||
ovp$k_ascii_max = 10, ! \.le;\size of ascii dn character set
|
||
ovp$k_asciix_max = 35, ! \.le;\size of ascii dn extended char set
|
||
ovp$k_ebcdic_max = 10, ! \.le;\size of ebcdic dn character set
|
||
ovp$k_sixbit_max = 10; ! \.le;\size of sixbit dn character set
|
||
! ;.end list
|
||
|
||
declare_class ('dnum') ! call declare_class
|
||
!
|
||
! The code following the call to declare_class is actually the body of the
|
||
! MACRO dt_class_dnum_def.
|
||
!
|
||
%EXPAND
|
||
data_type ('DN6LO', 'DN6LO', 6, sys_lcg, dnd$k_lead_over, 'sixbit', 18)
|
||
%EXPAND
|
||
data_type ('DN6LS', 'DN6LS', 6, sys_lcg, dnd$k_lead_sep, 'sixbit', 19)
|
||
%EXPAND
|
||
data_type ('DN6TO', 'DN6TO', 6, sys_lcg, dnd$k_trail_over, 'sixbit', 18)
|
||
%EXPAND
|
||
data_type ('DN6TS', 'DN6TS', 6, sys_lcg, dnd$k_trail_sep, 'sixbit', 19)
|
||
%EXPAND
|
||
data_type ('DN6U', 'DN6U', 6, sys_lcg, dnd$k_unsigned, 'sixbit', 18)
|
||
%EXPAND
|
||
data_type ('DN7LO', 'DN7LO', 7, sys_lcg, dnd$k_lead_over, 'ascii', 18)
|
||
%EXPAND
|
||
data_type ('DN7LS', 'DN7LS', 7, sys_lcg, dnd$k_lead_sep, 'ascii', 19)
|
||
%EXPAND
|
||
data_type ('DN7TO', 'DN7TO', 7, sys_lcg, dnd$k_trail_over, 'ascii', 18)
|
||
%EXPAND
|
||
data_type ('DN7TS', 'DN7TS', 7, sys_lcg, dnd$k_trail_sep, 'ascii', 19)
|
||
%EXPAND
|
||
data_type ('DN7U', 'DN7U', 7, sys_lcg, dnd$k_unsigned, 'ascii', 18)
|
||
%EXPAND
|
||
data_type ('DN8LO', 'DN8LO', 8, sys_8bit, dnd$k_lead_over, 'ascii', 31)
|
||
%EXPAND
|
||
data_type ('DN8LS', 'DN8LS', 8, sys_8bit, dnd$k_lead_sep, 'ascii', 32)
|
||
%EXPAND
|
||
data_type ('DN8TO', 'DN8TO', 8, sys_8bit, dnd$k_trail_over, 'asciix',31)
|
||
%EXPAND
|
||
data_type ('DN8TS', 'DN8TS', 8, sys_8bit, dnd$k_trail_sep, 'ascii', 32)
|
||
%EXPAND
|
||
data_type ('DN8U', 'DN8U', 8, sys_8bit, dnd$k_unsigned, 'ascii', 31)
|
||
%EXPAND
|
||
data_type ('DN9LO', 'DN9LO', 9, sys_lcg, dnd$k_lead_over, 'ebcdic', 18)
|
||
%EXPAND
|
||
data_type ('DN9LS', 'DN9LS', 9, sys_lcg, dnd$k_lead_sep, 'ebcdic', 19)
|
||
%EXPAND
|
||
data_type ('DN9TO', 'DN9TO', 9, sys_lcg, dnd$k_trail_over, 'ebcdic', 18)
|
||
%EXPAND
|
||
data_type ('DN9TS', 'DN9TS', 9, sys_lcg, dnd$k_trail_sep, 'ebcdic', 19)
|
||
%EXPAND
|
||
data_type ('DN9U', 'DN9U', 9, sys_lcg, dnd$k_unsigned, 'ebcdic', 18)
|
||
|
||
%EXPAND
|
||
end_class ! call MACRO end_class
|
||
|
||
%SBTTL 'Display Numeric date table (DND)'
|
||
!++
|
||
! .hl 3 Display Numeric data table (>dnd>)
|
||
! The format for the display numeric data table is below. This
|
||
! table is indexed by the data subtype (within its class).
|
||
!
|
||
! .literal
|
||
!--
|
||
$field
|
||
dnd_fields =
|
||
SET
|
||
!++ copy
|
||
dnd$v_byt_siz = [$bits(6)], ! byte size
|
||
dnd$v_sys_orig = [$bits(3)], ! system of origin
|
||
dnd$v_sign_type = [$bits(3)], ! sign type indicator
|
||
dnd$v_ovp_max_index = [$byte], ! maximum index of OVP
|
||
dnd$v_max_length = [$bits(6)], ! maximum field length
|
||
dnd$v_char_set = [$bits(3)] ! character set code
|
||
!-- .end literal
|
||
|
||
TES;
|
||
|
||
LITERAL dnd$k_size = $field_set_size;
|
||
|
||
MACRO
|
||
dtt_dn ! \.p;Macro >\
|
||
!++
|
||
! declares an item to have the right structure and field attributes for the
|
||
! display numeric data table.
|
||
!--
|
||
= BLOCKVECTOR [dt_class_dnum_max + 1, dnd$k_size]
|
||
FIELD (dnd_fields) % ;
|
||
|
||
%SBTTL 'Class Packed Decimal data type definitions'
|
||
!++
|
||
! .hl 2 Class Packed Decimal
|
||
! .index class packed decimal
|
||
!
|
||
! Information to be provided for each data type:
|
||
! .list 1, "o"
|
||
! .le;Name as quoted string
|
||
! .le;Short name as quoted string
|
||
! .le;Byte size
|
||
! .le;System of origin
|
||
! .le;Maximum length allowed
|
||
! .le;Name of sign set to be used. Note that valid sign set names are:
|
||
! .list
|
||
! .le;DECSTD
|
||
! .index packed decimal sign set names
|
||
! .end list
|
||
! .le;size of sign set
|
||
! .end list
|
||
!--
|
||
|
||
! ; Literal for packed decimal sign table sizes:
|
||
LITERAL ! ;.s1.list 0, "o"
|
||
pds$k_decstd_max = 6; ! \.le;\
|
||
! ;.end list
|
||
|
||
! ; Literals for packed decimal sign set reference codes:
|
||
LITERAL ! ;.s 1 .list 0, "o"
|
||
ss_decstd = 0, ! ;.le;ss_decstd -- DEC-10/DEC-20 COBOL and VAX COBOL packed decimal standard sign set
|
||
ss_max = 1; ! ;.end list
|
||
|
||
declare_class ('pdec')
|
||
!
|
||
! The code following the call to declare_class is actually the body of the
|
||
! MACRO dt_class_pdec_def.
|
||
!
|
||
%EXPAND
|
||
data_type ('PD8', 'PD8', 8, 4, sys_8bit, 31, 'decstd')
|
||
%EXPAND
|
||
data_type ('PD9', 'PD9', 9, 4, sys_lcg, 18, 'decstd')
|
||
%EXPAND
|
||
end_class ! call MACRO end_class
|
||
|
||
%SBTTL 'Packed Decimal data table (PDD)'
|
||
!++
|
||
! .hl 3 Packed decimal data table (>pdd>)
|
||
! Format for the packed decimal data table. This table is indexed
|
||
! by the data subtype (within its class).
|
||
!
|
||
! .literal
|
||
!--
|
||
|
||
$field
|
||
pdd_fields =
|
||
SET
|
||
!++ copy
|
||
pdd$v_byt_siz = [$bits(6)], ! byte size
|
||
pdd$v_nbl_siz = [$bits(6)], ! nibble size (within a byte)
|
||
pdd$v_sys_orig = [$bits(3)], ! system of origin
|
||
pdd$v_max_length = [$byte], ! maximum field length
|
||
pdd$v_sign_set = [$bits(4)] ! addr of sign table to use
|
||
!-- .end literal
|
||
TES;
|
||
|
||
LITERAL pdd$k_size = $field_set_size;
|
||
|
||
MACRO
|
||
dtt_pd ! \.p;Macro >\
|
||
!++
|
||
! Declares an item to have the right structure and field attributes for
|
||
! the packed decimal data table.
|
||
!--
|
||
= BLOCKVECTOR [dt_class_pdec_max + 1, pdd$k_size]
|
||
FIELD (pdd_fields) % ;
|
||
|
||
%SBTTL 'Clean up'
|
||
|
||
LITERAL ! ; .hl 2 Maximum class code value
|
||
dix$k_max_class = dt_class; ! \ .p;Maximum class code used: >
|
||
! ; This is set to max class code used.
|
||
|
||
%PRINT (dix$k_max_class, '=', %NUMBER (dix$k_max_class))
|
||
|
||
!
|
||
! Clean up
|
||
!
|
||
|
||
UNDECLARE
|
||
dt_class,
|
||
dt_code,
|
||
%QUOTE declare_class,
|
||
%QUOTE data_type,
|
||
%QUOTE end_class;
|
||
|
||
%SBTTL 'Short routine names for BLISS36'
|
||
|
||
!++
|
||
! .hl 1 Short routine names for BLISS36
|
||
! Short routine names are needed for all global routines, for use by BLISS36.
|
||
! To make things look as neat as possible, this will be done by defining
|
||
! macros with the long names, which expand to the short names.
|
||
!
|
||
! Here are the long and short name equivalences:
|
||
! .list 0, "o"
|
||
!--
|
||
|
||
%IF %BLISS (BLISS36)
|
||
%THEN
|
||
|
||
MACRO
|
||
!
|
||
! Routines
|
||
!
|
||
!++ copy /strip .le;
|
||
dix$$bit_offset = dixbof %,
|
||
dix$$check_alignment = dixcal %,
|
||
dix$$check_ffd = dixcfd %,
|
||
dix$$check_type = dixctp %,
|
||
dix$$con_cb_fb = dixcxb %,
|
||
dix$$con_cb_xi = dixcxx %,
|
||
dix$$con_cf_fp = dixcxf %,
|
||
dix$$con_fbin = dixfbn %,
|
||
dix$$con_fb_cb = dixbxc %,
|
||
dix$$con_fb_xi = dixbxx %,
|
||
dix$$con_fp = dixfp %,
|
||
dix$$con_fp_cf = dixfxc %,
|
||
dix$$con_gen = dixgen %,
|
||
dix$$con_str = dixstr %,
|
||
dix$$con_dn = dixdn %,
|
||
dix$$con_dn_xi = dixdxx %,
|
||
dix$$con_xi_dn = dixxxd %,
|
||
dix$$con_pd = dixpd %,
|
||
dix$$con_pd_xi = dixpxx %,
|
||
dix$$con_xi_pd = dixxxp %,
|
||
dix$$con_xi_cb = dixxxc %,
|
||
dix$$con_xi_fb = dixxxb %,
|
||
dix$$con_dn_pd = dixdxp %,
|
||
dix$$con_dn_fb = dixdxf %,
|
||
dix$$con_pd_dn = dixpxd %,
|
||
dix$$con_pd_fb = dixpxf %,
|
||
dix$$con_fb_pd = dixfxp %,
|
||
dix$$con_fb_dn = dixfxd %,
|
||
dix$$copy_structure = dixcpy %,
|
||
dix$$des_by_det = dixdbd %,
|
||
dix$$fetch_bits = dixfbt %,
|
||
dix$$get_argadr = dixadr %,
|
||
dix$$incr_des = dixifd %,
|
||
dix$$adj_xi_scal = dixajx %,
|
||
dix$$port_hand = dixpeh %,
|
||
dil$$return_kludge = dilret %,
|
||
dix$$round_cf = dixrcf %,
|
||
dix$$stuff_bits = dixsbt %,
|
||
dil$$usr_intrfc_hand = diluih %,
|
||
dix$by_det = cvgen %,
|
||
dix$by_dix_des = xcgen %, ! [8] Insert missing pseudonym
|
||
dil$init = dilini %,
|
||
dix$mak_des_det = xdescr %,
|
||
dix$xcvpd = xcvpd %,
|
||
dix$xcvdn = xcvdn %,
|
||
dix$xcvfb = xcvfb %,
|
||
dix$xcvfp = xcvfp %,
|
||
dix$xcvst = xcvst %,
|
||
dix$xcfbdn = xcfbdn %,
|
||
dix$xcfbpd = xcfbpd %,
|
||
dix$xcdnfb = xcdnfb %,
|
||
dix$xcdnpd = xcdnpd %,
|
||
dix$xcpddn = xcpddn %,
|
||
dix$xcpdfb = xcpdfb %,
|
||
!-- .end list
|
||
!
|
||
! ; Data structures need short names, too:
|
||
!
|
||
! ;.list 0, "o"
|
||
!++ copy /strip .le;
|
||
dil$a_copyright = cpyrgh %, ! [7]
|
||
dil$g_module_version = modver %, ! [7]
|
||
dil$g_version = dilver %, ! [7]
|
||
dil$k_version = %NAME ('DIL%VE') %, ! [7]
|
||
dit$k_version = %NAME ('dit%ve') %, ! [7]
|
||
dix$a_copyright = cpyrgh %, ! [7]
|
||
dix$acst_ascii = dixasc %,
|
||
dix$acst_ebcdic = dixebc %,
|
||
dix$acst_sixbit = dixsix %,
|
||
dix$adtt_fbin = dixfbd %,
|
||
dix$adtt_fp = dixfpd %,
|
||
dix$adttx_st = dixsdx %,
|
||
dix$adtt_st = dixstd %,
|
||
dix$adtt_dn = dixdnd %,
|
||
dix$adtt_pd = dixpdd %,
|
||
dix$at_max_dt_cod = dixmdt %,
|
||
dix$ag_sys_bpunit = dixbpu %,
|
||
dix$g_module_version = modver %, ! [7]
|
||
dix$g_version = dixver %, ! [7]
|
||
dix$gg_debug = dixdbf %,
|
||
dil$gg_return_severity = dilsev %,
|
||
dil$gg_return_msg_id = dilmid %,
|
||
dil$gg_return_stat_val = dilstv %,
|
||
dix$g_library_version = libver %, ! [7]
|
||
dix$g_dixcst_version = cstver %, ! [7]
|
||
dix$k_dixcst_version = %NAME ('CST%VE') %, ! [7]
|
||
dix$k_version = %NAME ('DIX%VE') %, ! [7]
|
||
dix$adnovp_ascii = dixoa %,
|
||
dix$adnovp_asciix = dixoax %,
|
||
dix$adnovp_ebcdic = dixoe %,
|
||
dix$adnovp_sixbit = dixos %,
|
||
dix$apds_decstd = dixpds %;
|
||
!-- .end list
|
||
;
|
||
%FI ! End %IF %BLISS (BLISS36)
|
||
|
||
!++
|
||
! .HL 1 Clean up after XPORT
|
||
! XPORT seems to be in the habit of leaving the following definition
|
||
! lying around, but won't tolerate its existence at the start of a
|
||
! file. Therefore it must be UNDECLAREd here:
|
||
!--
|
||
|
||
UNDECLARE ! \\
|
||
%QUOTE $descriptor; ! \\
|