Trailing-Edge
-
PDP-10 Archives
-
tops20-v7-ft-dist1-clock
-
7-sources/dap.b36
There are 5 other files named dap.b36 in the archive. Click here to see a list.
MODULE DAP( !DAP message processing routines
IDENT='7.0(664) 6-Feb-87'
%BLISS36(,
ENTRY(
D$GCFG, ! DAP$GET_CONFIG, ! Get Config message
D$GATT, ! DAP$GET_ATTRIBUTES, ! Get Attributes -> FAB
D$$GAT, ! DAP$$GET_ATTRIBUTES,! Get Attributes FAB+FST
D$PCFG, ! DAP$PUT_CONFIG, ! Build CONFIG
D$PATT, ! DAP$PUT_ATTRIBUTES, ! Build ATTRIBUTES <- FAB
D$$PAT, ! DAP$$PUT_ATTRIBUTES,! Put Attributes FAB+FST
D$PACC, ! DAP$PUT_ACCESS, ! Build ACCESS message
D$PNAM, ! DAP$PUT_NAME, ! Build a NAME message
D$PCTL, ! DAP$PUT_CONTROL, ! Build CONTROL message
D$GSTS ! DAP$GET_STATUS ! Process a STATUS message
))
)=
BEGIN
!
! COPYRIGHT (C) DIGITAL EQUIPMENT CORPORATION 1981, 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.
!
!++
! FACILITY: RMS-20
!
! ABSTRACT: This is the System-independent part of the DAP protocol.
!
!
! ENVIRONMENT: TOPS-20, Transportable BLISS DecNet Interface
!
! AUTHOR: Andrew Nourse, CREATION DATE: 21-Dec-81
! RMS edit numbers:
!
! 664 - Add output of FFB and EBK fields so that NFT's DIR command works.
! 656 - Implement protection XAB code in get and put attributes messages.
! 653 - Don't default the MRS to 512 unless the RFM is UDF and all of the
! following is true: no MRS was specified, we are talking to a 10 or 20,
! the TYP is IMAGE (correcting part of edit 647).
! 652 - If we are talking to an old non-RMS TOPS-20 program then add two to the
! MRS if the RFM is STM and default the FOP to SUP if none specified.
! 647 - Default the datatype to IMAGE if it wasn't given in the attributes
! message. If we are doing image mode, default the bytesize to 36 and
! MRS of 512 if not given in attribute message and we are talking to an
! LCG machine. The TOPS-10 NFT program depends on this working right
! since it uses SEQ mode for image file transfers.
! 645 - If image mode to another 36 bit system running old FALs, set block
! size 512 and byte size 36 and undefined record format.
! 644 - Insure that all three arguments passed to DAP$GET_CONFIG.
! 641 - Nametype_Nam NAME message must be preceded by structure and
! directory NAME messages, else ignore it.
! 636 - Allow RSTS to read stream files.
! 623 - Construct keyed $GET string keys with proper byte pntr.
! 620 - Old missing dot in D$PCTL caused infinite loop on keyed $GET.
! 617 - Old typo moving DAP FLG bits.
! 613 - Added DIL8 type class to support DIL formatted 8-bit
! records generated (only) by DIU)
! 610 - Fix extended KEY attributes, implement KNM sending/receiving,
! don't compare checksums if requested to do so but we are
! closing and deleting a file, fix "Unsupported DAP operation"
! error for directory/list function from VMS when bit 35 is on.
! 606 - Handle 8-segment keys,
! also add more UAPointer calls to D$Name_Decompose
! 605 - Handle oversize RFA's from/to VMS
! 602 - Default ORG & some other fields if not returned, fix dev & sdc
! 601 - Check for RMS$_SIZ
! 600 - Don't lose RFA on PUT
! 577 - Handle strange ALLOC & KEY messages correctly
! Handle certain status messages better
! 574 - Use FST from global, handle ext attrs better
! 572 - TOPS10
! 571 - Fix returned names & $display
! 557 - Fix multistream
! 555 - Fix LSA
! New names for software version fields
! 515 - Use Xab$v_Cod, not Xab$h_Bid
! 533 - Save Accopt for CRC
!
! Module edit numbers:
! 20 - Handle overlong fields in STATUS message better
! 17 - Handle XABs better
! 16 - RMS'ify. And the DIB is now an FST
! 15 - Make DAP$$(GET|PUT)_ATTRIBUTES, which takes a DIB as an argument
! 14 - Make DAP$GET_ATTRIBUTES return if it gets ACCESS msg
! 13 - Make losing old FAL-20 blocks into pages
! 12 - Handle ADT. also put BDT and PDT in correct order
! 11 - Put nodeid in resultant name generated from 3-part name
! 10 - Send real byte size to 36-bit machines, no byte size to others
! and include node name in remote resultant filespec.
! 07 - Set implied CRLF for ASCII FIXED
! 06 - Workaround RSTS not sending STATUS for file-not-found on directory
! 05 - Put in ENTRY points
! 04 - Fix default for BLS in DAP$PUT_ATTRIBUTES
! and put in bitvectors for workarounds
! - Fix RENAME name type
! 03 - Page mode
! 02 - Make the FOP go out
! 01 - The beginning
!--
!
! Libraries
!
REQUIRE 'RMSREQ';
LIBRARY 'BLISSNET';
LIBRARY 'CONDIT';
!
! Table of Contents
!
FORWARD ROUTINE
DAP$GET_CONFIG, ! Get Config message
DAP$GET_ATTRIBUTES, ! Get Attributes
DAP$$GET_ATTRIBUTES, ! Get Attributes to FAB & FST
D$NAME_DECOMPOSE: NOVALUE, ! decompose remote filespec
DAP$PUT_CONFIG: NOVALUE, ! Build CONFIG
DAP$PUT_ATTRIBUTES: NOVALUE, ! Build ATTRIBUTES from FAB
DAP$$PUT_ATTRIBUTES: NOVALUE, ! Build Attributes from FAB & FST
DAP$PUT_ACCESS: NOVALUE, ! Build ACCESS message
DAP$PUT_NAME: NOVALUE, ! Build a NAME message
DAP$PUT_CONTROL: NOVALUE, ! Build CONTROL message
DAP$GET_STATUS, ! Process a STATUS message
DAP$RFA_RMS_DAP: NOVALUE, ! Convert RMS RFA for DAP
DAP$RFA_DAP_RMS; ! Convert DAP RFA for RMS
!
! Literals
!
%IF NOT %DECLARED(Fab$k_SLf) ! If RMS does not have STREAM_CRLF
%THEN LITERAL Fab$k_SLf = Fab$k_Stm;! make it STREAM
%FI
%IF NOT %DECLARED(Fab$k_SCr) ! If RMS does not have STREAM_CRLF
%THEN LITERAL Fab$k_SCr = Fab$k_Stm;! make it STREAM
%FI
%IF %BLISS(BLISS36)
%THEN
%IF %SWITCHES(TOPS20)
%THEN
LITERAL
OUR_OSTYPE=DAP$K_TOPS20,
OUR_BLOCK_SIZE=512,
DEVICE_NAME_LENGTH=40, ! Including punctuation
DIRECTORY_NAME_LENGTH=41,!
FILE_NAME_LENGTH=40, !
OUR_FILESYS=DAP$K_RMS20;
%ELSE
LITERAL
OUR_OSTYPE=DAP$K_TOPS10,
OUR_BLOCK_SIZE=512,
DEVICE_NAME_LENGTH=40, ! Including punctuation
DIRECTORY_NAME_LENGTH=45,!
FILE_NAME_LENGTH=40, !
OUR_FILESYS=DAP$K_TOPS10;
%FI
%ELSE %ERROR('Not implemented for 16/32 bit architectures')
%FI;
!
! External references
!
EXTERNAL ROUTINE Chazac,
s$fbbyv,
s$fbsiz,
S$StrDt,
S$DtStr,
Dap$Get_Header,
Dap$Unget_Header,
Dap$Get_Byte,
Dap$Get_2byte,
Dap$Get_Date,
Dap$Get_Variable_String,
Dap$Get_Variable_Counted,
Dap$Size_Bitvector,
Dap$Get_Bitvector,
Dap$Get_Longword,
Dap$Get_Variable_Counted,
Dap$Put_Bitvector,
Dap$Put_Header,
Dap$Put_2byte,
Dap$Put_Longword,
Dap$Put_Byte,
Dap$Put_String,
Dap$Put_Variable_Counted,
Dap$Put_Date,
Dap$Unget_Byte,
Dap$Eat_Message,
Dap$Error_Dap_Rms,
UAddr,
UAPointer,
TGUPointer;
EXTERNAL
d$gtrace: BITVECTOR[%BPVAL];
!
! Macros
!
MACRO Dap_Error (Ddesc, Mac, Mic) = Signal ( Err_Ds ( Mac, Mic), Ddesc ) %;
!
! Equated Symbols
!
LITERAL Dap$k_Obj_Fal=17; !The FAL Object Type
!
! GLOBAL Data
!
PSECT GLOBAL=$HIGH$;
PSECT OWN=$HIGH$;
GLOBAL FalObj: INITIAL (Dap$k_Obj_Fal) ;
!+ 610
! Global vector of addresses for dynamically allocated KeyName
! text buffers
!-
GLOBAL KnmBuf: VECTOR[256] INITIAL (0) ; !610
!
! This is the configuration XAB that describes what we are running
!
GLOBAL OurCfg: $XabCfg_decl PRESET
([xab$h_bid] = xab$k_bid, ! Set up header !a545
[xab$h_bln] = xab$k_cfglen, ! !a545
[xab$v_cod] = xab$k_cfg, ! !a545
[xab$b_version]=7,
[xab$b_econum]=0,
[xab$b_softver]=3,
[xab$b_ostype]=Our_OSType,
[xab$b_filesys]=Our_Filesys,
[xab$h_bufsiz]=Dap$k_Buffer_Size,
! System Capabilities
[xab$v_preallocation]=1, ! pre ! Preallocation supported
! File Organizations Supported:
[xab$v_sequential_org]=1, ! sqo ! Sequential
[xab$v_relative_org]=1, ! rlo ! Relative
[xab$v_direct_org]=0, ! dro ! DIRECT (reserved)
[xab$v_control_extend]=0, ! ext ! Control message $EXTEND
!
! File Access Modes Supported:
[xab$v_sequential_transfer]=1, ! sqt ! Sequential File Transfer
! Random access by
[xab$v_random_access_recnum]=1, ! rre ! Record Number
[xab$v_random_access_vbn]=1, ! rvb ! Virtual Block # !m561
[xab$v_random_access_key]=1, ! rke ! Key
[xab$v_random_access_hash]=0, ! rha ! hash code (reserved)
[xab$v_random_access_rfa]=1, ! rrf ! RFA
[xab$v_indexed_multi_key]=1, ! imk ! Multi-key ISAM
[xab$v_switch_access_mode]=1, ! swa ! Change RAC !m545
[xab$v_append_access]=1, ! apa ! APPEND supported
[xab$v_submit_access]=1, ! sba ! Control message $SUBMIT
[xab$v_data_compression]=0, ! cmp ! Reserved
[xab$v_multi_data_streams]=0, ! mds ! Multiple record streams
[xab$v_display]=1, ! dis ! Control message $DISPLAY
! DAP Message blocking:
[xab$v_blocking]=1, ! blr ! Until response needed
[xab$v_unrestricted_blocking]=1, ! blu ! Unrestricted
[xab$v_len256]=1, ! 256 ! Extended length field
[xab$v_checksum]=1, ! chk ! DAP checksumming
! XAB messages supported
[xab$v_key_definition]=1, ! kem ! KEY DEFINITION message
[xab$v_allocation]=1, ! alm ! ALLOCATION message
[xab$v_summary]=1, ! smm ! SUMMARY message
[xab$v_directory]=1, ! dir ! DIRECTORY access
[xab$v_date_time]=1, ! dtm ! DATE/TIME message
[xab$v_protection]=1, ! pro ! PROTECTION message
[xab$v_acl]=0, ! acl ! ACL message (reserved)
! FOP Close bits supported:
[xab$v_fop_print]=1, ! fpr ! FOP SPL bit
[xab$v_fop_submit]=1, ! fsb ! FOP SCF bit
[xab$v_fop_delete]=1, ! fde ! FOP DLT bit
[xab$v_default_filespec]=0, ! dfs ! Default Filespec !m545
[xab$v_sequential_access]=1, ! sqa ! Sequential RECORD access
[xab$v_recovery]=0, ! rec ! Recovery (Reserved)
[xab$v_bitcnt]=1, ! bit ! BITCNT field
[xab$v_warning_status]=0, ! war ! WARNING STATUS message
[xab$v_rename_access]=1, ! ren ! $RENAME
[xab$v_wildcarding]=1, ! wld ! Wildcarding
[xab$v_go_no_go]=0, ! go ! GO/NOGO option
[xab$v_name]=1, ! nam ! NAME message
[xab$v_segmenting]=1, ! seg ! DAP message segmentation
! $CLOSE Options
[xab$v_change_attributes]=0, ! cat ! Change Attributes
[xab$v_change_dtm]=0, ! cdt ! Change Date/Time
[xab$v_change_protection]=0, ! cpr ! Change Protection
[xab$v_change_name]=1, ! cna ! Change Name
[xab$v_modified_attributes]=0, ! mat ! Changed Attributes/Create
[xab$v_display_3_part_name]=1, ! d3n ! 3-part name in $DISPLAY
[xab$v_rename_change_attributes]=0,! rat ! Change Attributes
[xab$v_rename_change_dtm]=0, ! rdt ! Change Date/Time
[xab$v_rename_change_protection]=0,! rpr ! Change Protection
[xab$v_blkcnt]=0, ! bcs ! Block Count
[xab$v_Octal_Version_Numbers]=0 ! ovn ! octal version numbers
);
!
! Canned Messages (Global PLITS)
!
GLOBAL D_Skip: $Xpn_Descriptor (Binary_Data= (3, UPLIT(Char8(Dap$k_Continue,
0,
Dap$k_Con_Skip))));
! Runtime conditionals for workarounds (to other systems' bugs)
GLOBAL
T20bug: BITVECTOR[16] INITIAL(-1), ! Bit map for TOPS-20 workarounds
Vmsbug: BITVECTOR[16] INITIAL(-1), ! for VMS
Rsxbug: BITVECTOR[16] INITIAL(-1), ! for RSX
Rstbug: BITVECTOR[16] INITIAL(-1), ! for RSTS
Rtbug: BITVECTOR[16] INITIAL(-1), ! for RT11
Iasbug: BITVECTOR[16] INITIAL(-1), ! for IAS
Posbug: BITVECTOR[16] INITIAL(-1), ! for POS
Ultbug: BITVECTOR[16] INITIAL(-1), ! for ULTRIX
Msdbug: BITVECTOR[16] INITIAL(-1), ! for MS-DOS
T10bug: BITVECTOR[16] INITIAL(-1); ! for TOPS-10
OWN D_Null: $Str_Descriptor ( String = %CHAR(0) );
GLOBAL ROUTINE Dap$Get_Config ( P_Dd: REF $Dap_Descriptor,
P_Cfg: REF $XabCfg_Decl,
p_fab: REF $fab_decl)= !a637
!++
! FUNCTIONAL DESCRIPTION:
!
! Process a CONFIG message and save the information contained therein
! into the configuration block
!
! FORMAL PARAMETERS:
!
! p_dd: Address of DAP message descriptor
! p_cfg: Address of internal configuration XAB to fill in
! p_fab: Address of user's FAB (so that we may fill in his config XAB)
!
! IMPLICIT INPUTS:
!
! NONE
!
! IMPLICIT OUTPUTS:
!
! Internal configuration block is set up and user's configuration XAB is
! set up (if any).
!
! ROUTINE VALUE:
! COMPLETION CODES:
!
! DAP Message type of message we got.
!
! SIDE EFFECTS:
!
! NONE
!
!--
BEGIN
BIND dd=.P_dd: $Dap_Descriptor;
BIND Cfg=.P_Cfg: $XabCfg_Decl;
BIND ufab = .p_fab: $fab_decl;
LOCAL xabptr;
IF Dap$Get_Header (dd) NEQ DAP$K_CONFIG
THEN RETURN Dap$Unget_Header (dd);
Cfg[Xab$h_Bufsiz]=Dap$Get_2byte(dd); !Maximum DAP message size
Cfg[Xab$b_Ostype]=Dap$Get_Byte(dd); !What are we talking to
Cfg[Xab$b_Filesys]=Dap$Get_Byte(dd); !File system type
Cfg[Xab$b_Version]=Dap$Get_Byte(dd); !DAP Version # of remote system
Cfg[Xab$b_Econum]=Dap$Get_Byte(dd); !DAP ECO #
Cfg[Xab$b_Usrnum]=Dap$Get_Byte(dd); !Customer version # for DAP
Cfg[Xab$b_Softver]=Dap$Get_Byte(dd); !Version of cusp
Cfg[Xab$b_Usrsoft]=Dap$Get_Byte(dd); !User cusp version #
Dap$Get_Bitvector(dd,Cfg[Xab$v_Syscap],12); !SYSCAP bits
IF .Dd[Dap$h_Length] GTR 0 !If Message was longer
THEN Dap$Eat_Message (dd); ! ignore the rest
! a637vv
! Fill in user's config xab (if any) from the internal config block
xabptr = .ufab[Fab$a_Xab]; ! Point to the first xab
WHILE .xabptr NEQ 0 ! While the xab chain still points
DO BEGIN ! Look for the config xab
BIND uxab = uaddr(.xabptr): $xabcfg_decl;
IF .uxab[XAB$V_COD] EQL XAB$K_CFG ! Is it a config xab?
THEN BEGIN ! Yes
IF .rmssec EQL 0 ! Copy non-header portion of config
THEN $move_words(cfg+XAB$K_HDRLEN,
uxab+XAB$K_HDRLEN,
XAB$K_CFGLEN-XAB$K_HDRLEN) ! Section 0 mover
ELSE $rms$xcopy(cfg+XAB$K_HDRLEN,
uxab+XAB$K_HDRLEN,
XAB$K_CFGLEN-XAB$K_HDRLEN); ! Section nonzero mover
EXITLOOP; ! We found it now exit
END
ELSE xabptr=.uxab[XAB$A_NXT]; ! On to next XAB
END; ! End of WHILE .xabptr NEQ 0 DO
! a637^^
Dap$k_Config !Return what we got
END; !End of DAP$GET_CONFIG
GLOBAL ROUTINE Dap$Get_Attributes ( P_Dd: REF $Dap_Descriptor,
P_Fab: REF $Fab_Decl)=
!++
! FUNCTIONAL DESCRIPTION:
!
! Process ATTRIBUTES, ATTRIBUTES extensions, NAME and ACCESS messages
! Returns on receipt of ACK or ACCESS (or NAME if DAP$K_RENAME)
!
! FORMAL PARAMETERS:
!
! P_DD: Addr of DAP message descriptor
! P_FAB: Addr of FAB
! This routine uses the FST pointed to by the global FST
!
! ROUTINE VALUE:
!
! DAP Operator code if successful, Signal error otherwise
!
! SIDE EFFECTS:
!
! Memory is allocated for a KDB for each Key message read.
! These are kept in a chain from Fst[Fst$a_Kdb]
!--
BEGIN
DAP$$GET_ATTRIBUTES( .p_dd, .p_Fab, .Fst )
![15] Call this routine to really do the work, using the FST from the FAB
END;
GLOBAL ROUTINE Dap$$Get_Attributes (p_Dd: REF $Dap_Descriptor,
P_Fab: REF $Fab_Decl,
p_Fst: REF $Rms_Fst )=
!++
! FUNCTIONAL DESCRIPTION:
!
! Process ATTRIBUTES, ATTRIBUTES extensions, NAME and ACCESS messages
! Returns on receipt of ACK or ACCESS (or NAME if DAP$K_RENAME)
!
! FORMAL PARAMETERS:
!
! P_DD: Addr of DAP message descriptor
! P_FAB: Addr of (RMS) FAB
! P_FST: Addr of Fst
!
! ROUTINE VALUE:
!
! DAP Operator code if successful, Signal error otherwise
!
! SIDE EFFECTS:
!
! Memory is allocated for a KDB for each Key message read.
! These are kept in a chain from Fst[Fst$a_Kdb]
!--
BEGIN !Expecting ATTRIBUTES, ACCESS, NAME, ACK,
!or any of the Attributes extensions
BIND dd=.P_dd: $Dap_Descriptor,
fab=.p_fab: $Fab_Decl,
fst=.p_fst: $Rms_Fst,
Config=.Fst[Fst$a_Config]: $XabCfg_Decl; ! Configuration block
BIND typ = ( IF .Fab[Fab$a_Typ] NEQ 0
THEN .Fab[Fab$a_Typ]
ELSE 0 ): $Typ_decl; !a504
LOCAL mtype: INITIAL(-1); !DAP message type
LOCAL omtype;
LOCAL nametypes_seen: BITVECTOR[21] INITIAL(0); ! Types of Name messages seen
LOCAL ! Pointers to the various XABs
xabptr,
xaball: VECTOR[32] INITIAL(0),
xabpro: REF $XabPro_decl INITIAL(0),
xabcfg: REF $XabCfg_decl INITIAL(0),
xabsum: REF $XabSum_decl INITIAL(0),
xabdat: REF $XabDat_decl INITIAL(0),
xabkey: VECTOR[256] INITIAL(0); ! We can have 255 of these!
! Find our XABs ![17] Handle XABs better vv
xabptr = .Fab[Fab$a_Xab];
WHILE .xabptr NEQ 0
DO
BEGIN
BIND uxab=UAddr( .xabptr ): $XabKey_decl;
CASE .Uxab[Xab$v_Cod] FROM 0 TO Xab$k_cod_max OF ! COD not BID !m515
SET
[Xab$k_Sum]: XabSum=uxab;
[Xab$k_All]: BEGIN
MAP uxab: $XabAll_decl;
XabAll[ .uxab[Xab$b_aid] ] = uxab;
END;
[Xab$k_Dat]: XabDat=uxab;
[Xab$k_Cfg]: ;
[Xab$k_Key]: XabKey[ .uxab[Xab$b_ref] ] = uxab;
[Xab$k_Pro]: XabPro=uxab;
[OUTRANGE]: SIGNAL( Rms$_Cod, .uxab[Xab$v_cod] );
TES;
xabptr=.uxab[Xab$a_nxt]; ! On to next XAB
END;
WHILE 1 DO
BEGIN
LABEL Do_Name;
omtype=.mtype;
mtype=Dap$Get_Header(DD[$]);
SELECTONE .MTYPE OF SET
[DAP$K_ATTRIBUTES]:
BEGIN
LOCAL attmenu: BITVECTOR[42] INITIAL(0),
datatype: BITVECTOR[14] INITIAL(0),
org: INITIAL(0),
rfm: INITIAL(0),
rat: BITVECTOR[21] INITIAL(0),
bls: INITIAL(0),
mrs: INITIAL(0),
alq: INITIAL(0),
bks: INITIAL(0),
mrn: INITIAL(0),
runsys: VECTOR[CH$ALLOCATION(40)]
INITIAL(REP CH$ALLOCATION(40) OF (0)),
deq: INITIAL(0),
fop: BITVECTOR[42] INITIAL(0),
bsz: INITIAL(0),
dev: BITVECTOR[42] INITIAL(0),
sdc: BITVECTOR[42] INITIAL(0),
lrl: INITIAL(0),
hbk: INITIAL(0),
ebk: INITIAL(0),
ffb: INITIAL(0),
sbn: INITIAL(0);
Dap$Get_Bitvector (dd, attmenu, 6); !Attributes menu bits
! See if there is a datatype and read it. Default the datatype
! to IMAGE if none was specified.
IF .attmenu[DAP$V_ATTMENU_DAT] ! Datatype?
THEN DAP$GET_BITVECTOR (dd, datatype, 2) ! Yes read it
ELSE datatype[DAP$V_DATATYPE_IMAGE] = 1; ! No default it
IF .attmenu[Dap$v_Attmenu_Org] ! File Organization
THEN
BEGIN
org=Dap$Get_Byte(dd);
Fab[Fab$v_Org]=$Dap_Translate_Value(.org,
Dap$k_Org_,Fab$k_,
Seq,Rel,Idx,Hsh);
END
ELSE Fab[Fab$v_Org] = Fab$k_Seq; ! Default !m602
IF .attmenu[Dap$v_Attmenu_Rfm] ! Record Format
THEN
BEGIN
rfm=Dap$Get_Byte(dd);
Fab[Fab$v_Rfm]=$Dap_Translate_Value(.rfm,
Dap$k_Rfm_,Fab$k_,
Udf,Fix,Var,
Vfc,Stm,Lsa,
Slf,Scr); !m572
END
ELSE Fab[Fab$v_Rfm] = Fab$k_Fix; ! Default rfm !a561
IF .attmenu[Dap$v_Attmenu_Rat] ! Record Attributes
THEN
BEGIN
rat=Dap$Get_Byte(dd);
$Dap_Move_Bits ( Rat,Dap$v_Rat_,Fab,Fab$v_,
Ftn,Cr,Prn,Blk,Lsa );
END
ELSE Fab[Fab$h_Rat] = 0; !m602
Fst[Fst$h_Rat] = .Fab[Fab$h_Rat]; ! in FST also !m602
%BLISS36(
IF .rat[Dap$v_Rat_Lsa] ! Line-Sequenced Ascii
THEN
BEGIN
Fab[Fab$v_Rfm]=Fab$k_Lsa;
Fab[Fab$b_Fsz] = 2; ! Size of sequence # !a555
END;
! is a Record Format on the 10 & 20
! and a Record Attribute elsewhere
) !End %BLISS36
IF .attmenu[Dap$v_Attmenu_Bls]
THEN bls=Dap$Get_2byte(dd) ! Physical Block Size
ELSE bls=512; ! default
IF .attmenu[Dap$v_Attmenu_Mrs]
THEN Fab[Fab$h_Mrs]=Dap$Get_2byte(dd) ! Maximum Record Size
ELSE Fab[Fab$h_Mrs]=0; ! Default is 0 (unlimited) !m602
! If an old (non-rms) access from old TOPS-20 or DIL system
! then bump the MRS up by 2
IF .fab[FAB$H_MRS] NEQ 0
AND .fab[FAB$V_RFM] EQL FAB$K_STM
AND .config[XAB$B_OSTYPE] EQL XAB$K_TOPS20
AND .config[XAB$B_VERSION] LSS 7
THEN fab[FAB$H_MRS] = .fab[FAB$H_MRS] + 2;
IF .attmenu[Dap$v_Attmenu_Alq] ! Allocation Quantity
THEN
BEGIN ! in blocks
alq=Dap$Get_Longword (dd); ! of (BLS) bytes
! Convert blocks to pages if old TOPS-20 non-RMS FAL
! New FAL has FILESYS of RMS-20 ![13]
IF .config[Xab$b_Filesys] EQL Xab$k_Filesys_Tops20
THEN alq=.alq/4;
Fab[Fab$g_Alq]=.alq;
END
ELSE Fab[Fab$g_Alq]=0; ! default to 0 !m602
IF .attmenu[Dap$v_Attmenu_Bks] ! Bucket Size
THEN Fab[Fab$v_Bks]=Dap$Get_Byte(dd)
ELSE Fab[Fab$v_Bks]=0; ! Default !m602
IF .attmenu[Dap$v_Attmenu_Fsz] ! Fixed Header Size
THEN Fab[Fab$b_Fsz]=Dap$Get_Byte(dd) ! (of VFC record)
ELSE Fab[Fab$b_Fsz]=0; ! Default !m602
IF .attmenu[Dap$v_Attmenu_Mrn] ! Maximum Record Number
THEN Fab[Fab$g_Mrn]=Dap$Get_Longword(dd)
ELSE Fab[Fab$g_Mrn]=0; ! Default !m602
IF .attmenu[Dap$v_Attmenu_Run] ! Runtime System
THEN Dap$Get_Variable_String (dd,CH$PTR(runsys),40);
! Put in temp and forget it
IF .attmenu[Dap$v_Attmenu_Deq] ! Default Extension Quantity
THEN deq=Dap$Get_2byte(dd); ! Eat it
! Get the FOP. If no FOP specified in the menu and we are
! talking to an old non-RMS TOPS-20 program, set the SUP bit
IF .attmenu[DAP$V_ATTMENU_FOP] ! File Options?
THEN BEGIN ! Yes
DAP$GET_BITVECTOR (dd, fop, 6);
$DAP_MOVE_BITS(Fop,Dap$v_Fop_,Fab,Fab$v_,
Rwo,Rwc,Pos,Dlk,Lck,
Ctg,Sup,Nef,Tmp,Mkd,Dmo,
Wck,Rck,Cif,Lko,Sqo,Mxv,Spl,
Scf,Dlt,Cbt,Wat,Dfw,Tef,Drj);
END
ELSE IF .config[XAB$B_OSTYPE] EQL XAB$K_TOPS20
AND .config[XAB$B_VERSION] LSS 7
THEN fab[FAB$V_SUP] = TRUE;
!
! Set the byte size
!
IF .attmenu[Dap$v_Attmenu_Bsz] !Byte size
THEN bsz=Dap$Get_Byte(dd) !m571
ELSE bsz=8;
! Compute file class if image was specified.
IF .datatype[DAP$V_DATATYPE_IMAGE] ! Image mode?
THEN BEGIN ! Yes, check carefully
! If the machine is not a LCG machine and image was
! specififed, then image mode is really 8 bit byte mode.
! The -10 expects us to default to 36 bit bytes if no bsz
! was specified and we have selected image mode somehow.
fst[FST$H_FILE_CLASS] = TYP$K_BYTE; ! First guess
IF .config[XAB$B_OSTYPE] EQL XAB$K_TOPS20 ! orange
OR .config[XAB$B_OSTYPE] EQL XAB$K_TOPS10 ! blue?
THEN BEGIN
fst[FST$H_FILE_CLASS] = TYP$K_IMAGE; ! 36-bit image
IF NOT .attmenu[DAP$V_ATTMENU_MRS] ! No MRS?
AND .fab[FAB$V_RFM] EQL FAB$K_UDF ! RFM is UDF?
THEN fab[FAB$H_MRS] = 512; ! Default 512
IF NOT .attmenu[DAP$V_ATTMENU_BSZ] ! No bsz?
THEN bsz = 36; ! default 36
END;
! Don't think we need this anymore -GAS
!IF .bsz EQL %BPUNIT ! These are not Bytes
!THEN fst[Fst$h_File_Class] = Typ$k_Image;
! Default RSTS RFM is ASCII stream, and type ASCII.
IF .config[XAB$B_OSTYPE] EQL XAB$K_RSTS ! Is it RSTS
AND .rstbug[RST_BUG_NO_RFM_SPEC] ! always buggy
AND NOT .attmenu[DAP$V_ATTMENU_RFM] ! No RFM spec
THEN fab[FAB$V_RFM] = FAB$K_STM; ! Default rfm
! Non LCG systems call (almost) everything IMAGE because
! it's all bytes to them. Sometimes we can tell by the
! presence of record attributes that are only valid for
! ASCII files. If one of those are seen then set ASCII.
IF (.Fab[Fab$v_Rfm] EQL Fab$k_Stm) !a555
OR (.Fab[Fab$v_Rfm] EQL Fab$k_Lsa)
OR (.Fab[Fab$h_Rat]
AND (Fab$m_CR+Fab$m_Emb+Fab$m_Prn+Fab$m_Ftn))
THEN Fst[Fst$h_File_Class] = Typ$k_Ascii;
! Check for MACY11 format. (NOTE: Nobody uses this and it
! doesn't work right in RMSFAL/RMS/FFF, NFT, FTS, and the
! old FAL.)
IF .Fab[Fab$v_Macy11]
THEN Fst[Fst$h_File_Class] = Typ$k_Macy11;
END; ! End of image mode checks
! Set the byte size (may have been changed above)
fst[FST$H_BSZ] = fab[FAB$V_BSZ] = .bsz; ! Set byte size
IF .attmenu[Dap$v_Attmenu_Dev]
THEN
BEGIN
Dap$Get_Bitvector(dd, dev, 6); !Device characteristics
$Dap_Move_Bits(Dev,Dap$v_Dev_,Fab,Dev$v_,
Rec,Ccl,Trm,Mdi,Sdi,Sqd,Nul,
Fod,Shr,Spl,Mnt,Dmt,All,Idv,
Odv,Swl,Avl,Elg,Mbx,Rtm,Rad,
Rck,Wck,For,Net,Gen); !m602
END;
IF .attmenu[Dap$v_Attmenu_Sdc]
THEN
BEGIN
Dap$Get_Bitvector (dd, sdc, 6);
$Dap_Move_Bits(sdc,Dap$v_Dev_,Fab,Sdc$v_,
Rec,Ccl,Trm,Mdi,Sdi,Sqd,Nul,
Fod,Shr,Spl,Mnt,Dmt,All,Idv,
Odv,Swl,Avl,Elg,Mbx,Rtm,Rad,
Rck,Wck,For,Net,Gen); !m602
END; ! spooling device characteristics
IF .attmenu[Dap$v_Attmenu_Lrl]
THEN lrl=Dap$Get_2byte(dd);
IF .attmenu[Dap$v_Attmenu_Hbk]
THEN hbk=Dap$Get_Longword(dd);
IF .attmenu[Dap$v_Attmenu_Ebk]
THEN ebk=Dap$Get_Longword(dd);
IF .attmenu[Dap$v_Attmenu_Ffb]
THEN ffb=Dap$Get_2byte(dd);
IF .attmenu[Dap$v_Attmenu_Sbn]
THEN sbn=Dap$Get_Longword(dd);
!+
! Return the file class to the user
! unless he wants to override it
!-
IF Typ NEQ 0 !a504
THEN
IF .Typ[Typ$h_Class] EQL 0
THEN Typ[Typ$h_Class] = .Fst[Fst$h_File_Class];
END; ! End of Attributes Message
[DAP$K_DATE_TIME]: !Date & time extension message
BEGIN
LOCAL dtmstr: VECTOR[CH$ALLOCATION(18)];
LOCAL d_dtmstr: $STR_DESCRIPTOR();
LOCAL dtmmenu: BITVECTOR[14]; !Menu for this message
LOCAL rvn; ! Revision number
CLEARV (dtmmenu);
$Str_Desc_Init(Desc=d_Dtmstr, String=(18,CH$PTR(dtmstr)));
!d544
IF .xabdat NEQ 0 ! If we found a Date/Time XAB
THEN
BEGIN
Dap$Get_Bitvector(dd, dtmmenu, 2);
IF .dtmmenu[Dap$v_Dtm_Cdt] ! Creation date time
THEN BEGIN
Dap$Get_Date(dd,CH$PTR(dtmstr));
xabdat[Xab$g_Cdt]=S$Strdt(d_dtmstr);
END;
IF .dtmmenu[Dap$v_Dtm_Rdt] ! Read date time
THEN BEGIN
Dap$Get_Date(dd,CH$PTR(dtmstr));
xabdat[Xab$g_Rdt]=S$Strdt(d_dtmstr);
END;
IF .dtmmenu[Dap$v_Dtm_Edt] ! Scratch date time
THEN BEGIN
Dap$Get_Date(dd,CH$PTR(dtmstr));
xabdat[Xab$g_Edt]=S$Strdt(d_dtmstr);
END;
IF .dtmmenu[Dap$v_Dtm_Rvn] ! Revision number
THEN rvn=Dap$Get_2byte(dd);
IF .dtmmenu[Dap$v_Dtm_Bdt] ! Backup date time
THEN BEGIN
Dap$Get_Date(dd,CH$PTR(dtmstr));
!When we put this in the RMS block we can save it
!xabdat[Xab$g_Bdt]=s$Strdt(d_dtmstr);
END;
IF .dtmmenu[Dap$v_Dtm_Pdt] ! Internal date time
THEN BEGIN
Dap$Get_Date(dd,CH$PTR(dtmstr));
!When we put this in the RMS block we can save it
!xabdat[Xab$g_Pdt]=s$Strdt(d_dtmstr);
END;
IF .dtmmenu[Dap$v_Dtm_Adt] ! Access date time ![12]
THEN BEGIN
Dap$Get_Date(dd,CH$PTR(dtmstr));
!When we put this in the RMS block we can save it
!xabdat[Xab$g_Adt]=s$Strdt(d_dtmstr);
END;
END
ELSE Dap$Eat_Message(dd); ! No place to put it
END;
[DAP$K_PROTECTION]: ! Protection extension message
BEGIN
IF .xabpro NEQ 0 ! If we have a protection XAB
THEN BEGIN ! Then fill it in
LOCAL promenu: BITVECTOR[14] INITIAL(0);
Dap$Get_Bitvector(dd, promenu, 2); ! Get the menu
IF .promenu[Dap$v_Protmenu_Owner] ! Owner protection
THEN BEGIN
%IF %DECLARED (XABPRO$A_OWNER)
%THEN
xabpro[Xabpro$h_Owner_Length]=
Dap$Get_Variable_String(dd,
.xabpro[Xabpro$a_Owner],
.xabpro[Xabpro$h_Owner_Size])
%ELSE
BEGIN ! If owner area then eat the owner string
LOCAL owner: VECTOR[CH$ALLOCATION(40)];
Dap$Get_Variable_String(dd,CH$PTR(owner),40);
END;
%FI;
END;
IF .promenu[DAP$V_PROTMENU_PROTSYS] ! System protection
THEN BEGIN
LOCAL prot: BITVECTOR[21] INITIAL(0);
Dap$Get_Bitvector(dd, prot, 3);
xabpro[XAB$V_PROTSYS] = .prot;
END;
IF .promenu[Dap$v_Protmenu_Protown] ! Owner protection
THEN BEGIN
LOCAL prot: BITVECTOR[21] INITIAL(0);
Dap$Get_Bitvector(dd, prot, 3);
xabpro[XAB$V_PROTOWN] = .prot;
END;
IF .promenu[DAP$V_PROTMENU_PROTGRP] ! Group protection
THEN BEGIN
LOCAL prot: BITVECTOR[21] INITIAL(0);
Dap$Get_Bitvector(dd, prot, 3);
xabpro[XAB$V_PROTGRP] = .prot;
END;
IF .promenu[DAP$V_PROTMENU_PROTWLD] ! World protection
THEN BEGIN
LOCAL prot: BITVECTOR[21] INITIAL(0);
Dap$Get_Bitvector(dd, prot, 3);
xabpro[XAB$V_PROTWLD] = .prot;
END;
END
ELSE Dap$Eat_Message (dd);
END;
[Dap$k_Summary]:
BEGIN
IF .xabsum NEQ 0
THEN
BEGIN
LOCAL SumMenu: BITVECTOR[42] INITIAL(0);
Dap$Get_Bitvector( dd, SumMenu, 6 );
IF .SumMenu[Dap$v_SumMenu_Nok]
THEN xabsum[Xab$b_Nok]=Dap$Get_Byte( Dd );
IF .SumMenu[Dap$v_SumMenu_Noa]
THEN xabsum[Xab$b_Noa]=Dap$Get_Byte( Dd );
! Ignore NOR(1) and PVN(2)
END;
Dap$Eat_Message( Dd );
END;
[Dap$k_Allocation]:
BEGIN !m573v
LOCAL
allmenu: BITVECTOR[42] INITIAL(0),
aid: INITIAL(0), ! Area id for this xab
ad: REF $Rms_Adb[Rms$k_Max_Areas] INITIAL(.Fst[Fst$a_Adb]);
! Make an ADB if we haven't got one (first allocation msg)
IF .ad EQL 0 !a573v
THEN
BEGIN
$XPO_GET_MEM( UNITS=Adb$k_MaxBln, RESULT=ad, FILL=0 );
ad[adb$h_bid]=Adb$k_Bid;
ad[adb$h_bln]=Adb$k_MaxBln;
END; !a573^
Dap$Get_Bitvector( dd, allmenu, 6 );
IF .Allmenu[Dap$v_Allmenu_Vol]
THEN Dap$Get_2Byte( dd ); ! Ignore
IF .Allmenu[Dap$v_Allmenu_Aln]
THEN
BEGIN
LOCAL Aln: BITVECTOR[28];
Dap$Get_Bitvector( dd, Aln, 4 ); ! Ignore !m577
END;
IF .Allmenu[Dap$v_Allmenu_Aop]
THEN
BEGIN
LOCAL Aop: BITVECTOR[28];
Dap$Get_Bitvector( dd, Aop, 4 ); ! Ignore
END;
IF .Allmenu[Dap$v_Allmenu_Loc]
THEN Dap$Get_Byte( dd ); ! Ignore
IF .Allmenu[Dap$v_Allmenu_Rfi]
THEN Dap$Get_Variable_Counted( dd, 0, 16 ); ! Ignore
IF .Allmenu[Dap$v_Allmenu_Alq]
THEN Dap$Get_Longword( dd ); ! Ignore
IF .Allmenu[Dap$v_Allmenu_Aid]
THEN aid=Dap$Get_Byte( Dd ); ! Area Id
If .XabSum NEQ 0
THEN IF .aid GEQ .XabSum[Xab$b_Noa]
THEN XabSum[Xab$b_Noa] = .Aid+1;
IF .Allmenu[Dap$v_Allmenu_Bkz]
THEN ad[Adb$v_bkz,.Aid]=Dap$Get_Byte( Dd );
IF .Allmenu[Dap$v_Allmenu_Deq]
THEN Dap$Get_2Byte( dd ); ! Ignore
IF .xaball[.aid] NEQ 0
THEN
BEGIN
BIND allxab=.xaball[.aid]: $XabAll_decl;
allxab[Xab$b_bkz]=.ad[Adb$v_Bkz,.aid];
END
END; !m573^
[Dap$k_Key]: !610 rewritten
BEGIN
LOCAL
KeyMenu: BITVECTOR[42] INITIAL(0),
krf,
thiskdb: REF $Rms_Kdb,
nsg: INITIAL(0),
flg: BITVECTOR[18] INITIAL(0),
Dfl: INITIAL(0),
Ifl: INITIAL(0),
Ian: INITIAL(0),
Lan: INITIAL(0),
Dan: INITIAL(0),
Dtp: INITIAL(0);
$XPO_GET_MEM( RESULT=thiskdb, UNITS=Kdb$k_Bln, FILL=0 ); !m573
BEGIN !m573v
LOCAL lastkdb: REF $Rms_Kdb INITIAL(.Fst[Fst$a_Kdb]);
IF .lastkdb EQL 0
THEN Fst[Fst$a_Kdb] = .thiskdb
ELSE
BEGIN
WHILE .lastkdb[kdb$a_nxt] NEQ 0
DO lastkdb=.lastkdb[kdb$a_nxt];
lastkdb[kdb$a_nxt]=.thiskdb;
END;
END; !m573^
thiskdb[kdb$h_bid]=kdb$k_bid;
thiskdb[kdb$h_bln]=kdb$k_bln;
!+ 610
! Store every relevant field from the DAP message into the KDB first.
! Then, if there already is a local XAB chain, store the fields there
! too. Note that no local XAB chain will exist when this routine
! is called by the FAL.
!-
Dap$Get_Bitvector( Dd, Keymenu, 6 ); ! Get the menu
IF .Keymenu[Dap$v_Keymenu_Flg]
THEN
BEGIN
Dap$Get_Bitvector( Dd, flg, 2 );
$Dap_Move_Bits( flg, dap$v_flg_, !617
thiskdb, kdb$v_,
dup, chg, hsh );
END;
!+ 610
! DFL and IFL are slightly smelly, since there is no Kdb field
! which is used to store the user's XAB value directly. However,
! storing the user's DAP values in the DFL/IFL offset Kdb fields
! should be OK: If the FAL is calling this routine in response to
! an ACCESS request, it will eventually transfer the Kdb data
! directly to its own XAB chain; if this routine is being called
! by the sender after an ACCESS to process returned attributes,
! it never looks at the Kdb chain anyway...
!-
IF .Keymenu[Dap$v_Keymenu_Dfl]
THEN
thiskdb[kdb$h_dfl_offset] =
dfl =
Dap$Get_2Byte( Dd );
IF .Keymenu[Dap$v_Keymenu_Ifl]
THEN
thiskdb[kdb$h_ifl_offset] =
ifl =
Dap$Get_2Byte( Dd );
!
! Now get the position and size of each segment
!
IF .KeyMenu[Dap$v_Keymenu_Nsg]
THEN nsg = Dap$Get_Byte( Dd ); !m577
INCR i from 0 to .nsg-1
DO
BEGIN
BIND SegVec=thiskdb[Kdb$z_Segments]: BLOCK; !m573
SegVec[ .i, %FIELDEXPAND(xab$h_pos0, 1), 18, 0 ] =
Dap$Get_2Byte( dd );
SegVec[ .i, %FIELDEXPAND(xab$h_siz0, 1), 18, 0 ] =
Dap$Get_Byte( dd );
END;
IF .Keymenu[Dap$v_Keymenu_Ref]
THEN krf = Dap$Get_Byte( Dd )
ELSE krf=0;
thiskdb[Kdb$h_Reference]=.krf; ! Store ref in KDB
!+ 610
! KNM is special. If we have a DAP KNM text but no local key XAB
! chain to store its pointer in, get a block of dynamic memory for
! the text and store a pointer to it in the KNMBUF pointer vector.
! If the KNMBUF pointer already exists, clear its block for re-use.
! If there is a local key XAB and it has a KNM pointer, use that
! pointer and read the DAP text into where it points; if there is
! no pointer in the XAB's KNM field, read the DAP text and ignore it.
! Note the following: DAP KNM fields can be 40 bytes long, while
! RMS-20 limits KNMs to 30 bytes; VMS always sends a DAP KNM of
! 32 (decimal) length padded with null bytes, regardless of the
! actual length of the text.
!-
IF .Keymenu[Dap$v_Keymenu_Knm]
THEN
BEGIN
LOCAL KnmPtr: INITIAL(0);
IF .xabkey[.krf] NEQ 0
THEN
BEGIN
BIND keyxab = UAddr(.xabkey[.krf]): $XabKey_decl;
IF .keyxab[Xab$a_Knm] NEQ 0
THEN
BEGIN
knmPtr = UAddr(.keyxab[Xab$a_Knm]);
$clear (.KnmPtr,(Knmcharsiz/(%BPVAL/7)));
END;
END
ELSE
BEGIN
IF .KnmBuf[.krf] NEQ 0
THEN
BEGIN
KnmPtr = .KnmBuf[.krf];
$clear (.KnmPtr,(40/(%BPVAL/8)));
END
ELSE
BEGIN
$XPO_GET_MEM( RESULT=KnmBuf[.krf],
UNITS=(40/(%BPVAL/8)),FILL=0);
KnmPtr = .KnmBuf[.krf];
END;
END;
BEGIN
LOCAL KnmTxt: BYTE8VECTOR[40] INITIAL(0);
Dap$Get_Variable_String (
dd,
CH$PTR(KnmTxt),
40 );
IF .KnmPtr NEQ 0
THEN
BEGIN
IF .rmssec EQL 0
THEN $move_words ( KnmTxt,
.KnmPtr,
(Knmcharsiz/(%BPVAL/7)))
ELSE $Rms$Xcopy ( KnmTxt,
.KnmPtr,
(Knmcharsiz/(%BPVAL/7)));
END;
END;
END; !KNM
IF .Keymenu[Dap$v_Keymenu_Nul] ! Ignore
THEN Dap$Get_Byte( dd );
IF .Keymenu[Dap$v_Keymenu_Ian]
THEN
thiskdb[kdb$b_ian] =
Ian =
Dap$Get_Byte( Dd );
!+ 610
! Read the LAN (it will go only into the local XAB chain)
!-
IF .Keymenu[Dap$v_Keymenu_Lan]
THEN
Lan =
Dap$Get_Byte( Dd );
IF .Keymenu[Dap$v_Keymenu_Dan]
THEN
thiskdb[kdb$b_dan] =
Dan =
Dap$Get_Byte( Dd );
IF .KeyMenu[Dap$v_Keymenu_Dtp] !m571
THEN
thiskdb[kdb$v_datatype] =
Dtp =
$Dap_Translate_Value( Dap$Get_Byte( Dd ),
Dap$k_dtp_,
Xab$k_,
stg, ebc, six, pac, in4, fl1,
fl2, gfl, in8, as8, bn4, bn8 );
IF .XabSum NEQ 0
THEN
IF .krf GEQ .XabSum[Xab$b_Nok]
THEN XabSum[Xab$b_Nok] = .krf+1;
!+ 610
! Now store the relevant fields into the local XAB chain if one exists
!-
IF .xabkey[.krf] NEQ 0
THEN
BEGIN
BIND keyxab = UAddr(.xabkey[.krf]): $XabKey_decl; !m515
LOCAL keyseg: REF VECTOR;
keyseg=keyxab[xab$h_siz0]; !m515
$Dap_Move_Bits( flg, dap$v_flg_, !617
keyxab, xab$v_,
dup, chg, hsh );
keyxab[xab$b_ref]=.krf; ! key # for this XAB
INCR i from 0 TO .nsg-1
DO (BIND SegVec=thiskdb[Kdb$z_Segments]: VECTOR; !m573
keyseg[.i]=.SegVec[.i]); ! Copy pos/siz pairs
IF .Keymenu[Dap$v_Keymenu_Ian]
THEN keyxab[xab$b_Ian] = .Ian;
IF .Keymenu[Dap$v_Keymenu_Lan]
THEN keyxab[xab$b_Lan]=.Lan;
IF .Keymenu[Dap$v_Keymenu_Dan]
THEN keyxab[xab$b_Dan] = .Dan;
IF .KeyMenu[Dap$v_Keymenu_Dtp] !m571
THEN
keyxab[xab$v_dtp] = .Dtp;
! Ignore the remaining fields
END;
Dap$Eat_Message( Dd );
END;
[DAP$K_NAME]:
Do_Name:BEGIN
BIND nam=UAddr(.Fab[Fab$a_Nam]): $Nam_Decl; !m507
LOCAL filespec: VECTOR[CH$ALLOCATION(255)]; !Store filespec
LOCAL nametype: BITVECTOR[21];
LOCAL
nas; ! Length of name
LOCAL delim;
REGISTER dont_touch_me_there = 6; !m566
! This is because, if you pass a 1-word global byte pointer
! to a MOVSLJ or its fiends, it will turn it into a 2-word
! global. The people who wrote the BLISS compiler do not
! know this, and do not expect this register to get clobbered.
dont_touch_me_there = .dont_touch_me_there;
CLEARV ( nametype );
Dap$Get_Bitvector ( dd, nametype, 3);
IF (.nametype AND .nametypes_seen) NEQ 0
THEN RETURN Dap$Unget_Header(dd);
! If this is the second NAME message of this type for this call
! then it must be for the next file and should not be
! read until the next call (Directory List)
! So we regurgitate it and return
nametypes_seen=.nametypes_seen OR .nametype;
IF Nam EQL 0
THEN
BEGIN
Dap$Eat_Message ( dd );
! Must have a NAM block or ignore this message
LEAVE Do_Name;
END;
IF .nametype[Dap$k_Nametype_Str] ! Structure
THEN
BEGIN
Nam[Nam$a_Dev]=CH$PLUS( .Nam[Nam$a_Rsa],
.Nam[Nam$b_Node] );
Nam[Nam$b_Dev] = ! Store device here !m566
Dap$Get_Variable_String( dd,
UAPointer(.Nam[Nam$a_Dev]),
DEVICE_NAME_LENGTH);
Nam[Nam$a_Dir]=CH$PLUS( .Nam[Nam$a_Dev],
.Nam[Nam$b_Dev] );
Nam[Nam$v_Cha_Str]=1;
Nam[Nam$v_Wildcard]=1; ! Something is wildcarded
! (not necessarily this)
! (3-part name indicates this)
END;
IF .nametype[Dap$k_Nametype_Dir] ! Directory
THEN
BEGIN
Nam[Nam$b_Dir] = ! Store directory & length
Dap$Get_Variable_String(Dd,
UAPointer(.Nam[Nam$a_Dir]),
Directory_Name_Length);
Nam[Nam$a_Name]=CH$PLUS(.Nam[Nam$a_Dir],
.Nam[Nam$b_Dir]);
Nam[Nam$v_Cha_Dir]=1;
Nam[Nam$v_Wildcard]=1; ! Something is wildcarded
END;
IF .nametype[Dap$k_Nametype_Nam] ! File name
THEN
BEGIN
LOCAL D_Filespec: $str_Descriptor(Class=Dynamic);
LOCAL Bd_Filespec: $str_Descriptor(Class=Bounded);
LOCAL nas;
!+ 641
! If we have a name NAME message, but never got a directory
! or volume, eat it.
!-
IF NOT ((.Nametypes_Seen[Dap$k_Nametype_Dir])
AND (.Nametypes_Seen[Dap$k_Nametype_Str]))
THEN
BEGIN
Dap$Eat_Message ( dd );
LEAVE Do_Name;
END;
$STR_DESC_INIT(DESC=D_Filespec, CLASS=Dynamic);
$XPO_GET_MEM(DESC=D_Filespec, CHARACTERS=255);
Nas=Dap$get_Variable_String(Dd, ! Get file name in temp
.d_Filespec[Str$a_Pointer],
255);
$STR_DESC_INIT( DESC=BD_FILESPEC, CLASS=BOUNDED, !a572
STRING=(.nas, .d_filespec[STR$A_POINTER]));
D$Name_Decompose( bd_filespec, nam ); !m572
Nam[Nam$h_Rsl] = ! Recompute resultant length !a566
.Nam[Nam$b_Node] +
.Nam[Nam$b_Dev] +
.Nam[Nam$b_Dir] +
.Nam[Nam$b_Name] +
.Nam[Nam$b_Type] +
.Nam[Nam$b_Ver];
$XPO_FREE_MEM(STRING=D_FILESPEC);
END;
IF .NAMETYPE[DAP$K_NAMETYPE_FSP] ! Resultant filespec
THEN
BEGIN ! Store resultant filespec
LOCAL ressize; ! Length of resultant
IF (ressize=DAP$GET_BYTE(DD[$])) GTR 0 ! if non-null
THEN
BEGIN
Nam[Nam$a_Node]=.Nam[Nam$a_Rsa]; !d571
Nam[Nam$a_Dev]=CH$PLUS(.Nam[Nam$a_Node],
.Nam[Nam$b_Node]);
IF .ressize+.Nam[Nam$b_Node] GEQ .NAM[NAM$H_RSS]
THEN ! Make sure it will fit
SIGNAL(RMS$_NAM, 0, FAB[$]) ![11] Too big
ELSE
BEGIN
LOCAL rptr,
rlen;
rlen=.nam[NAM$H_RSS]-.nam[NAM$B_NODE]; !m571
rptr=UAPointer(.NAM[NAM$A_DEV]); !m571
Dap$Unget_Byte(dd); ! string getter needs count
nam[NAM$H_RSL]
=Dap$Get_Variable_String(dd,.rptr,.rlen)
+.nam[NAM$B_NODE];
IF .NameTypes_Seen[DAP$K_NAMETYPE_NAM] EQL 0 !m575
THEN
BEGIN
LOCAL rdesc: $STR_DESCRIPTOR( CLASS=BOUNDED,
STRING=(.rlen,.rptr) );
d$Name_decompose( rdesc, nam );
! Recompute resultant length
Nam[Nam$h_Rsl] = !a575
.Nam[Nam$b_Node] +
.Nam[Nam$b_Dev] +
.Nam[Nam$b_Dir] +
.Nam[Nam$b_Name] +
.Nam[Nam$b_Type] +
.Nam[Nam$b_Ver];
END;
END;
END;
END; !d571
END;
[Dap$k_Access]: ![14] Regurgitate
BEGIN ! and return
Dap$Unget_Header(dd); ! so access
RETURN Dap$k_Access; ! message getter
END; ! can get it
[Dap$k_Status]: ! Some sort of error from other end
RETURN Dap$Get_Status(dd); ! Get Status !d566
[Dap$k_Access_Complete]: ! Rename & Delete would return ACM
BEGIN
BIND Fst=.Fab[Fab$a_Ifi]: $Rms_Fst;
LOCAL cmpfunc;
LOCAL fop: BITVECTOR[42];
! Get the function code
cmpfunc=Dap$Get_Byte(dd);
! Get the FOP, if any
Dap$Get_Bitvector (dd, fop, 6);
$Dap_Move_Bits(fop,Dap$k_Fop_,Fab,Fab$v_,
Rwo,Rwc,Pos,Dlk,Lck,
Ctg,Sup,Nef,Tmp,Mkd,Dmo,
Wck,Rck,Cif,Lko,Sqo,Mxv,Spl,
Scf,Dlt,Cbt,Wat,Dfw,Tef,
Drj);
IF .dd[Dap$h_Bytes_Remaining] GTR 0
THEN
BEGIN
LOCAL checksum;
checksum=Dap$Get_2byte(dd);
! Do not expect checksum here, ($RENAME, $ERASE)
END;
CASE .cmpfunc FROM 1 TO Dap$k_Accomp_Max OF
SET
[Dap$k_Accomp_Response]:
BEGIN
Fst[Fst$v_File_Open] = ! No file open !a547
Fst[Fst$v_Access_Active]=0; ! Access is no longer active
!% FAL WORKAROUND
! If all we get is an ACCESS COMPLETE (without any attrs first)
! Then assume we cannot access the directory.
! For some reason TOPS-10 & TOPS-20 FALs do not give a status
! for this, but merely return immediate ACCESS COMPLETE!!!
! RSTS does exactly the same thing on file-not-found
IF (.omtype EQL -1) ! First message of this call?
AND (.T20bug[T20_Bug_No_Dir_Prv] ! And workaround enabled
OR .Rstbug[Rst_Bug_No_Dir_Fnf])
AND (.Fst[Fst$v_Display] NEQ 0) ! and we wanted attrs !m574
THEN
BEGIN
SELECT .Config[Xab$b_Ostype] OF
SET
[Dap$k_Tops20,
Dap$k_Tops10]: Fab[Fab$h_Sts]=Rms$_Prv; !m572
[Dap$k_Rsts]: Fab[Fab$h_Sts]=Rms$_Fnf;
[Dap$k_Tops20, Dap$k_Rsts]:
SIGNAL ( .Fab[Fab$h_Sts], 0, Fab);
TES;
END;
END;
[INRANGE]:
RETURN Dap$Unget_Header( dd ); ! Regurgitate
[OUTRANGE]: Dap_Error( dd, Dap$k_Mac_Sync,Dap$k_Access_Complete );
TES;
RETURN Dap$k_Access_Complete
END;
[DAP$K_ACK]:
BEGIN
Fst[Fst$v_Access_Active] = Fst[Fst$v_File_Open] = 1;
RETURN Dap$k_Ack; ! Normal exit from this routine
END;
[DAP$K_CONTINUE]: ! Eat leftover continue message !a566
BEGIN
Dap$Eat_Message( dd );
END;
[OTHERWISE]:
BEGIN
Dap_Error(dd, Dap$k_Mac_Sync,.dd[Dap$b_Operator]);
RETURN .dd[Dap$b_Operator]
END;
TES;
END; !WHILE 1
.mtype ! Return message type if we ever get here
END; !End of DAP$$GET_ATTRIBUTES (D$GATT) (process ATTRIBUTES)
ROUTINE d$name_decompose( pd_filespec: REF $Str_descriptor(CLASS=BOUNDED),
nam: REF $Nam_decl ) : NOVALUE =
BEGIN
BIND bd_filespec=.pd_filespec: $STR_DESCRIPTOR(CLASS=BOUNDED);
LOCAL delim;
DO
BEGIN
$Str_Scan( Remainder=Bd_Filespec, Substring=Bd_Filespec,
Delimiter=Delim,
Stop='.;<:[');
SELECT .delim OF
SET
[%C':']:
BEGIN
Str_Include( Bd_filespec, 1 ); ! Include :
Nam[Nam$b_Dev] = .Bd_filespec[Str$h_Length];
$Str_Copy( String=Bd_Filespec,
Target=(.Nam[Nam$b_Dev],
UAPointer(.Nam[Nam$a_Dev]) ) ); !m606
Nam[Nam$a_Dir] = Nam[Nam$a_Name]
= Nam[Nam$a_Type] = Nam[Nam$a_Ver]
= CH$PLUS( .Nam[Nam$a_Dev], .Nam[Nam$b_Dev] );
END;
[%C'<', %C'[']:
BEGIN
$Str_Scan( Remainder=Bd_Filespec, Substring=Bd_Filespec,
STOP='>]' );
Str_Include( Bd_filespec, 1 ); ! Include close bracket
Nam[Nam$b_Dir] = .Bd_filespec[Str$h_Length];
$Str_Copy( String=Bd_Filespec,
Target=(.Nam[Nam$b_Dir],
UAPointer(.Nam[Nam$a_Dir]) ) ); !m606
Nam[Nam$a_Name] = Nam[Nam$a_Type] = Nam[Nam$a_Ver]
= CH$PLUS( .Nam[Nam$a_Dir], .Nam[Nam$b_Dir] );
END;
[OTHERWISE]: EXITLOOP;
[ALWAYS]: Str_Exclude( Bd_Filespec, .Bd_Filespec[Str$h_Length] );
TES;
END WHILE 1;
Nam[Nam$b_Name]=.BD_Filespec[Str$h_Length];
$Str_Copy( String=Bd_Filespec, ! Store filename
Target=(.Nam[Nam$b_Name], UAPointer(.Nam[Nam$a_Name])) );
Nam[Nam$a_Type] = Nam[Nam$a_Ver]
= CH$PLUS(.Nam[Nam$a_Name], .Nam[Nam$b_Name]);
IF .delim EQL %C'.'
THEN
BEGIN
Bd_Filespec[Str$h_Length]=
.Bd_Filespec[Str$h_Length]+1; ! skip delimiter
$Str_Scan(Remainder=Bd_Filespec,
Substring=Bd_Filespec,
Delimiter=Delim,
Stop='.;<');
Str_Exclude( Bd_Filespec, -1 ); ! Put back . !a566
! a "negative exclude" is a leftward include.
Nam[Nam$b_Type]=.Bd_Filespec[Str$h_Length]; !m566
$Str_Copy( String=Bd_Filespec, !a566
Target=(.Nam[Nam$b_Type],
UAPointer(.Nam[Nam$a_Type])) );
Nam[Nam$a_Ver]=CH$PLUS( .Nam[Nam$a_Type],
.Nam[Nam$b_Type] );
END;
IF (.delim EQL %C';') OR (.delim EQL %C'.')
THEN ! Version/Generation number
BEGIN
$str_Scan(Remainder=Bd_Filespec,
Substring=Bd_Filespec,
Delimiter=.delim,
Span=';.0123456789-*'); ! Generation number
! store the length of generation number
! if it really is a generation number,
! i.e. .### or ;###.
! If we really got ;T or ;Afoo or ;P#####, ignore it.
IF .Bd_Filespec[Str$h_Length] GTR 1
THEN
BEGIN
Nam[Nam$b_Ver]=.Bd_Filespec[Str$h_Length];
$Str_Copy( String=Bd_Filespec,
Target=(.Nam[Nam$b_Ver],
UAPointer(.Nam[Nam$a_Ver])) );
END;
END;
END; !D$name_Decompose !m572^^
GLOBAL ROUTINE Dap$Put_Config (p_dd: REF $Dap_Descriptor, Bufsiz): NOVALUE=
!++
! FUNCTIONAL DESCRIPTION:
!
! Build a CONFIG message, using specified buffer size
!
! FORMAL PARAMETERS:
!
! P_DD: Addr of DAP message descriptor
! BUFSIZ: Buffer size to send to other system
!
!--
BEGIN
BIND dd=.p_dd: $Dap_Descriptor;
Init_Message (dd); !
dd[Dap$b_Operator]=Dap$k_Config; ! Build header
Dap$Put_Header( dd ); !
Dap$Put_2byte( dd, .Bufsiz ); ! Put buffersize
Dap$Put_Byte( dd, .OurCfg[Xab$b_OsType] ); ! Operating system type
Dap$Put_Byte( dd, .OurCfg[Xab$b_FileSys] ); ! File system type
Dap$Put_Byte( dd, .OurCfg[Xab$b_Version] ); ! Dap version (i.e. 7)
Dap$Put_Byte( dd, .OurCfg[Xab$b_EcoNum] ); ! Dap ECO (.e. 0 for 7.0)
Dap$Put_Byte( dd, .OurCfg[Xab$b_UsrNum] ); ! User mod level (7.0-1)
Dap$Put_Byte( dd, .OurCfg[Xab$b_DecVer] ); ! Dec software level
Dap$Put_Byte( dd, .OurCfg[Xab$b_UsrVer] ); ! User software level !m555
Dap$Put_Bitvector ( dd, OurCfg[Xab$v_Syscap], 12 ); ! system capabilities
END; ! DAP$PUT_CONFIG
GLOBAL ROUTINE Dap$Put_Attributes (P_Dd: REF $Dap_Descriptor,
P_Fab: REF $Fab_Decl) : NOVALUE=
!++
! FUNCTIONAL DESCRIPTION:
!
! Build attributes message from associated file block & send it.
!
! FORMAL PARAMETERS:
!
! P_DD: Address of a DAP descriptor
! P_FAB: Address of RMS FAB
! This routine uses the FST pointed to by the FAB
!
! IMPLICIT INPUTS:
!
! FST: Address of FST
!
! IMPLICIT OUTPUTS:
!
! An ATTRIBUTES message is put in the output buffer.
!--
BEGIN
BIND Dd=.P_dd: $Dap_Descriptor;
BIND Fab=.P_Fab: $Fab_Decl;
!d572
LOCAL display: BITVECTOR[32];
LOCAL xabptr;
LITERAL Create_Display_Mask =
NOT ( (1^Dap$v_Display_Summary)
OR 1^Dap$v_Display_3_Part_Name OR (1^Dap$v_Display_Name) ); !m574
! No name or summary message from accessing process, please !a545
display = .Fst[Fst$v_Display]; ! Get display bits from FST !m545
!d545
!
! Only send key & alloc xabs if opening file
!
Fst[Fst$v_Display]=
(SELECT .Fst[Fst$b_Operation] OF
SET
[Dap$k_Open,
Dap$k_Erase,
Dap$k_Rename]:
IF .Fst[Fst$v_Cif]
THEN .display AND Create_Display_Mask ! this may create !m545
ELSE 1^Dap$v_Display_Att; ! Main attributes only
[Dap$k_Create]: .display AND Create_Display_Mask !m545
TES);
!
! Send attributes and xab msgs as required
!
Dap$$Put_Attributes (Dd, Fab, .Fst);
Fst[Fst$v_Display]=.display; ! Set display bits for Access msg
END; ![15] Make this call another, so FAL can specify the FST separately
GLOBAL ROUTINE Dap$$Put_Attributes (P_Dd: REF $Dap_Descriptor,
P_Fab: REF $Fab_Decl,
P_Fst: REF $Rms_Fst): NOVALUE=
!++
! FUNCTIONAL DESCRIPTION:
!
! Build attributes message from associated file block & send it.
!
! FORMAL PARAMETERS:
!
! P_DD: Address of a DAP descriptor
! P_FAB: Address of FAB
! P_FST: Address of FST
!
! IMPLICIT OUTPUTS:
!
! An ATTRIBUTES message is put in the output buffer.
!
!--
BEGIN
BIND
dd=.P_Dd: $Dap_Descriptor,
Fab=.P_Fab: $Fab_Decl,
Fst=.P_Fst: $Rms_Fst,
Typ=UAddr(.Fab[Fab$a_Typ]): $Typ_Decl,
Nam=UAddr(.Fab[Fab$a_Nam]): $Nam_decl,
Config=.Fst[Fst$a_Config]: $XabCfg_Decl;
LOCAL
mlength: INITIAL(0), !Length of this message (data portion)
attmenu: BITVECTOR[42] INITIAL(0), !Attributes menu field
display: BITVECTOR[32] INITIAL(0), !Display bits
class,
datatype: BITVECTOR[14] INITIAL(0), !Data representation
org: INITIAL(0), !File organization
rfm: INITIAL(0), !Record format
rat: BITVECTOR[21] INITIAL(0), !Record attributes
bls: INITIAL(512), ![4] default=512 !Block size
mrs: INITIAL(0), !Record size
bks: INITIAL(0), !Bucket size
fsz: INITIAL(0), !Fixed portion size
runsys: BYTE8VECTOR[41] INITIAL(0), !Runtime system
deq: INITIAL(0), !Default extension quantity
bsz: INITIAL(0), !Byte size
dev: BITVECTOR[42] INITIAL(0), !Device characteristics
sdc: BITVECTOR[42] INITIAL(0), !Spooling dev characteristics
ffb: INITIAL(0), ! First free byte
ebk: INITIAL(0), ! Ending block number
nok: INITIAL(0),
noa: INITIAL(0),
nor: INITIAL(0),
BufKnm: BYTE8VECTOR[40] INITIAL(0), !610
fop: BITVECTOR[42] INITIAL(0);
! Following is duplicated from Dap$$Get_Attributes
LOCAL
xabptr,
xaball: VECTOR[32] INITIAL(0),
xabpro: REF $XabPro_decl INITIAL(0),
xabcfg: REF $XabCfg_decl INITIAL(0),
xabsum: REF $XabSum_decl INITIAL(0),
xabdat: REF $XabDat_decl INITIAL(0),
xabkey: VECTOR[256] INITIAL(0); ! We can have 255 of these!
! Find our XABs
xabptr = .Fab[Fab$a_Xab];
WHILE .xabptr NEQ 0
DO
BEGIN
BIND uxab=UAddr( .xabptr ): $XabKey_decl;
CASE .Uxab[Xab$v_Cod] FROM 0 TO Xab$k_cod_max OF ! COD not BID !m515
SET
[Xab$k_Sum]: XabSum=uxab;
[Xab$k_All]: BEGIN
MAP uxab: $XabAll_decl;
XabAll[ .uxab[Xab$b_aid] ] = uxab;
END;
[Xab$k_Dat]: XabDat=uxab;
[Xab$k_Cfg]: XabCfg=uxab;
[Xab$k_Key]: XabKey[ .uxab[Xab$b_ref] ] = uxab;
[XAB$K_PRO]: xabpro = uxab;
[OUTRANGE]: SIGNAL( Rms$_Cod, .uxab[Xab$v_cod] );
TES;
xabptr=.uxab[Xab$a_nxt]; ! On to next XAB
END;
! End of code duplicated from Dap$$Get_Attributes
Display=.Fst[Fst$v_Display]; ! Display flags
!+
! Build and send Attributes Message
!-
IF .Display[Dap$v_Display_Attributes]
THEN
BEGIN
bsz=.Fab[Fab$v_Bsz]; ! Byte size
mrs=.Fab[Fab$h_Mrs]; ! Max record size !a571
! Set up DATATYPE
Class = .Fst[Fst$h_File_Class]; ! We have determined a file class !m555
! already, use it
CASE .class FROM 0 TO Typ$k_Class_Max OF
SET
[0]: datatype = 0; ! Should not occur
[Typ$k_Ascii]:
BEGIN
datatype[Dap$v_Datatype_Ascii]=1;
bls=Our_Block_Size*(%BPVAL/.bsz); ! Block size in bytes
END; !d555
[Typ$k_Byte,
Typ$k_Image,
Typ$k_DIL8]: datatype[Dap$v_Datatype_Image]=1;
[Typ$k_Macy11]:
BEGIN
datatype[Dap$v_Datatype_Image]=1; ! Looks like image on remote
!% rat[Dap$v_Rat_Macy11]=1;
! Nobody supports this bit
END;
[OUTRANGE]: SIGNAL(Dap$_Aor,0,typ);
TES;
! The following is for support of file bytesize and count for NFT-20's
! directory command.
IF .config[XAB$B_FILESYS] EQL XAB$K_FILESYS_TOPS20 ! NFT?
THEN BEGIN ! It's a NFT directory command
LOCAL f_size, f_bpw, f_byv; ! Holds file size, bytes per wd
f_byv = s$fbbyv (.fab[FAB$H_JFN]); ! Get real byte size word
bsz = .f_byv<24,6>; ! BLISS wants it this way
f_bpw = 36 / .bsz; ! Compute bytes per word
bls = .f_bpw * 512; ! BLS is bytes_per_word * 512
f_size = s$fbsiz (.fab[FAB$H_JFN]); ! Get file size
ebk = 1 + (.f_size / .bls); ! Compute the EBK
ffb = .f_size MOD .bls; ! Compute FFB
END; ! End of filesys TOPS20 (NFT)
! If image mode, we need to supply certain defaults for 36 bit copies.
! A BSZ of other than 8 is not supported on non-36-bit systems. Default
! BSZ to 36 for 36-bit-systems.
!m645v
IF .class EQL TYP$K_IMAGE ! Is it image mode?
THEN BEGIN ! Yes, its image mode
IF .config[XAB$B_OSTYPE] EQL XAB$K_TOPS20 ! Is it a 36 bit
OR .config[XAB$B_OSTYPE] EQL XAB$K_TOPS10 ! system?
THEN BEGIN ! Yes, image/variable byte size systems
IF .config[XAB$B_FILESYS] NEQ XAB$K_FILESYS_RMS20
THEN BEGIN ! non-RMS-20 36-bit system image mode
fab[FAB$V_BSZ] = bsz = 36; ! 36 bit bytes
fab[FAB$V_RFM] = FAB$K_UDF; ! Undefined record format
fab[FAB$H_MRS] = bls = ! Get blocksize
(IF .config[XAB$B_OSTYPE] EQL XAB$K_TOPS10
THEN 128 ! TOPS-10 128 word blocks
ELSE 512); ! TOPS-20 512 word pages
END;
END
ELSE BEGIN ! Image and non-36-bit system
IF .bsz NEQ 8 ! And the bytesize is not 8
THEN BEGIN ! recalculate record size
LOCAL mrsw, bpw;
bpw = %BPVAL / .bsz; ! Bytes per word
mrsw = ( .mrs + .bpw - 1 ) / .bpw; ! words per record
mrs = ( ( .mrsw / 2 ) * 9 )
+ ( ( .mrsw AND 1 ) * 5 ); ! 8-bit bytes per rec
END;
bsz = 0; ! Don't send byte size to non-36-bit
END; ! End of image and non-36-bit system
END; ! End if image mode check
!m645^
! Device is a file-structured disk
Dev[Dap$V_Dev_Mdi]=Dev[Dap$V_Dev_Fod]=Dev[Dap$V_Dev_Shr]
=Dev[Dap$V_Dev_Mnt]=Dev[Dap$V_Dev_Idv]=Dev[Dap$V_Dev_Odv]
=Dev[Dap$V_Dev_Avl]=Dev[Dap$v_Dev_Elg]=Dev[Dap$v_Dev_Rad]=1;
!Turn on extension bits where needed & count # of bytes
BEGIN
LOCAL t;
t=Dap$Size_Bitvector (datatype, 2, 0);
IF (.t GTR 0) THEN
BEGIN
attmenu[Dap$v_Attmenu_Dat]=1; !Remember to send it
mlength=.mlength+.t; !Add approprioate # of bytes
END;
org=$Dap_Translate_Value(.Fab[Fab$v_Org],
Fab$k_,Dap$k_Org_,
Seq,Rel,Idx,Dir);
IF .org NEQ Dap$k_Org_Seq THEN
BEGIN
attmenu[Dap$v_Attmenu_Org]=1;
mlength=.mlength+1;
END;
!+
! Convert the Record Format
!-
BEGIN !m555vv
LITERAL Dap$k_Rfm_Lsa = Dap$k_Rfm_Vfc; ! Lsa is a form of VFC
! on the vax
rfm=$Dap_Translate_Value(.Fab[fab$v_Rfm], !Convert to DAP
Fab$k_,Dap$k_Rfm_, ! ex SCR & SLF
Udf,Fix,Var,Vfc,Stm, %(SCr,SLf,)% Lsa);
!m566
!+ 610
! Most remote systems can't understand TOPS LSA record format, so
! set DAP RAT to LSA only for RMS20 systems. The LSA RFM is converted
! to STM here, reconverted to LSA on the TOPS20 receiving end.
!-
IF .Fab[Fab$v_rfm] EQL Fab$k_Lsa
AND (.Config[Xab$b_FileSys] EQL Xab$k_FileSys_RMS20)
THEN
BEGIN
rfm=Dap$k_Rfm_Stm;
Rat[Dap$v_Rat_Lsa]=1;
END;
END;
IF .rfm NEQ Dap$k_Rfm_Fix THEN
BEGIN
attmenu[Dap$v_Attmenu_Rfm]=1;
mlength=.mlength+1;
END;
$Dap_Move_Bits(Fab,Fab$v_,rat,Dap$v_Rat_,
Ftn,Cr,Blk,Efc,Cbl,Lsa);
t=Dap$Size_Bitvector (rat, 3, 0);
IF .t GTR 0 THEN
BEGIN
attmenu[Dap$v_Attmenu_Rat]=1;
mlength=.mlength+.t;
END;
!
! BLS field
! If talking to NFT-20 always send it
! If talking to RSX-11 never send it
! Otherwise send it if it isn't 512.
!
IF (.bls NEQ 512
OR .config[XAB$B_FILESYS] EQL XAB$K_FILESYS_TOPS20)
AND (.rsxbug[RSX_BUG_NOT_WANT_BLS]
AND (.config[XAB$B_FILESYS] NEQ DAP$K_FILESYS_FCS11))
THEN attmenu[Dap$v_Attmenu_Bls] = 1;
IF .attmenu[Dap$v_Attmenu_Bls] ! If we are sending BLS
THEN mlength=.mlength+2; ! allow 2 bytes for it
!
! MRS field
!
!d571
IF .mrs NEQ 0 THEN
BEGIN
attmenu[Dap$v_Attmenu_Mrs]=1;
mlength=.mlength+2;
END;
IF .Fab[Fab$g_Alq] NEQ 0 THEN
BEGIN
attmenu[Dap$v_Attmenu_Alq]=1;
mlength=.mlength+$Dap_Size_Longword(.Fab[Fab$g_Alq]);
END;
IF .bks NEQ 0 THEN
BEGIN
attmenu[Dap$v_Attmenu_Bks]=1;
mlength=.mlength+1;
END;
IF .fsz NEQ 0 THEN
BEGIN
attmenu[Dap$v_Attmenu_Fsz]=1;
mlength=.mlength+1;
END;
IF .Fab[Fab$g_Mrn] NEQ 0
THEN
BEGIN
attmenu[Dap$v_Attmenu_Mrn]=1;
mlength=.mlength+$Dap_Size_Longword(.Fab[Fab$g_Mrn]);
END;
IF (t=.runsys[0]) NEQ 0 THEN
BEGIN
attmenu[Dap$v_Attmenu_Run]=1;
mlength=.mlength+.t;
END;
IF .deq NEQ 0 THEN
BEGIN
attmenu[Dap$v_Attmenu_Deq]=1;
mlength=.mlength+2;
END;
$Dap_Move_Bits (Fab, Fab$v_, fop, Dap$v_Fop_,
Rwo,Rwc,Pos,Dlk,Lck,
Ctg,Sup,Nef,Tmp,Mkd,Dmo,
Wck,Rck,Cif,Lko,Sqo,Mxv,Spl,
Scf,Dlt,Cbt,Wat,%(Dfw)% ,Tef,Drj); ! DFW not supported
! by most FALs
t=Dap$Size_Bitvector (fop, 6, 0);
IF .t GTR 0 THEN
BEGIN
attmenu[Dap$v_Attmenu_Fop]=1;
mlength=.mlength+.t;
END;
IF (.bsz NEQ 0) THEN ! Send BSZ unless 0
BEGIN
attmenu[Dap$v_Attmenu_Bsz]=1;
mlength=.mlength+1;
END;
t=Dap$Size_Bitvector (dev, 6, 0);
IF .t GTR 0 THEN
BEGIN
attmenu[Dap$v_Attmenu_Dev]=1;
mlength=.mlength+.t;
END;
t=Dap$Size_Bitvector (sdc, 6, 0);
IF .t GTR 0 THEN
BEGIN
attmenu[Dap$v_Attmenu_Sdc]=1;
mlength=.mlength+.t;
END;
IF .ebk NEQ 0 ! Send EBK and FFB if we need to
THEN BEGIN
attmenu[DAP$V_ATTMENU_EBK] = 1;
attmenu[DAP$V_ATTMENU_FFB] = 1;
mlength = .mlength + 2 + $DAP_SIZE_LONGWORD(.ebk);
END;
END; ! **
mlength = .mlength + $Dap_Size_Bitvector (Attmenu, 6);
Init_Message (dd);
Dd[Dap$b_Operator]=Dap$k_Attributes; ! This is attributes message
dd[Dap$v_Mflags_Length]=1; ! We will send length field
Dd[Dap$h_Length]=.mlength; ! Set up message length in header
Dap$Put_Header (dd); ! Build the message header
Dap$Put_Bitvector (dd,attmenu,6); !Menu field
IF .attmenu[Dap$v_Attmenu_Dat] THEN Dap$Put_Bitvector (dd, datatype, 2);
IF .attmenu[Dap$v_Attmenu_Org] THEN Dap$Put_Byte (dd, .org);
IF .attmenu[Dap$v_Attmenu_Rfm] THEN Dap$Put_Byte (dd, .rfm);
IF .attmenu[Dap$v_Attmenu_Rat] THEN Dap$Put_Bitvector (dd, rat, 3);
IF .attmenu[Dap$v_Attmenu_Bls] THEN Dap$Put_2byte (dd, .bls);
IF .attmenu[Dap$v_Attmenu_Mrs] THEN Dap$Put_2byte (dd, .mrs);
IF .attmenu[Dap$v_Attmenu_Alq] THEN Dap$Put_Longword (dd, .Fab[Fab$g_Alq]);
IF .attmenu[Dap$v_Attmenu_Bks] THEN Dap$Put_Byte (dd, .bks);
IF .attmenu[Dap$v_Attmenu_Fsz] THEN Dap$Put_Byte (dd, .fsz);
IF .attmenu[Dap$v_Attmenu_Mrn] THEN Dap$Put_Longword (dd, .Fab[Fab$g_mrn]);
IF .attmenu[Dap$v_Attmenu_Run]
THEN Dap$Put_Variable_Counted (dd, CH$PTR(runsys,0,8));
IF .attmenu[Dap$v_Attmenu_Deq] THEN Dap$Put_2byte (dd, .deq);
IF .attmenu[Dap$v_Attmenu_Fop] THEN Dap$Put_Bitvector (dd, fop, 6);
IF .attmenu[Dap$v_Attmenu_Bsz] THEN Dap$Put_Byte (dd, .bsz);
IF .attmenu[Dap$v_Attmenu_Dev] THEN Dap$Put_Bitvector (dd, dev, 6);
IF .attmenu[Dap$v_Attmenu_Sdc] THEN Dap$Put_Bitvector (dd, sdc, 6);
IF .attmenu[DAP$V_ATTMENU_EBK] THEN DAP$PUT_LONGWORD (dd, .ebk);
IF .attmenu[DAP$V_ATTMENU_FFB] THEN DAP$PUT_2BYTE (dd, .ffb);
END; ! End of Attributes Message
! Now send the DATE & TIME message if needed
IF .Config[Xab$v_Date_Time]
AND .XabDat NEQ 0
AND .Display[Dap$v_Display_DTM]
THEN BEGIN
LOCAL dtmmenu: BITVECTOR[42], !Menu for this message
cdt: VECTOR[CH$ALLOCATION(18)] INITIAL(0), !Create date
rdt: VECTOR[CH$ALLOCATION(18)] INITIAL(0), !Update date
edt: VECTOR[CH$ALLOCATION(18)] INITIAL(0), !Scratch date
cdtdesc: $Str_Descriptor( String=(18,CH$PTR(cdt))),
rdtdesc: $Str_Descriptor( String=(18,CH$PTR(rdt))),
edtdesc: $Str_Descriptor( String=(18,CH$PTR(edt)));
Clearv(dtmmenu); !initially 0
Init_Message(dd);
dd[Dap$h_Length]=1; !The menu field is always sent
dd[Dap$b_Operator] = Dap$k_Date_Time; ! Send a date-time msg !a545
IF .XabDat[Xab$g_Cdt] NEQ 0 THEN
BEGIN
dtmmenu[Dap$v_Dtm_Cdt]=1;
dd[Dap$h_Length]=19;
S$DtStr( .XabDat[Xab$g_Cdt], Cdtdesc );
END;
IF .XabDat[Xab$g_Rdt] NEQ 0 THEN
BEGIN
dtmmenu[Dap$v_Dtm_Rdt]=1;
dd[Dap$h_Length]=.dd[Dap$h_Length]+18;
S$DtStr( .XabDat[Xab$g_Rdt], Rdtdesc );
END;
IF .XabDat[Xab$g_Edt] NEQ 0 THEN
BEGIN
dtmmenu[Dap$v_Dtm_Edt]=1;
dd[Dap$h_Length]=.dd[Dap$h_Length]+18;
S$DtStr( .XabDat[Xab$g_Edt], Edtdesc );
END;
dd[Dap$v_Mflags_Length]=1; !Length field present
Dap$Put_Header (dd);
Dap$Put_Bitvector (dd, dtmmenu, 6); !Send the menu
!Dates are always 18-character fields
IF .dtmmenu[Dap$v_Dtm_Cdt]
THEN Dap$Put_Date (dd,.cdtdesc[Str$a_Pointer]); !Creation date
IF .dtmmenu[Dap$v_Dtm_Rdt]
THEN Dap$Put_Date (dd,.Rdtdesc[Str$a_Pointer]); !Revision date
IF .dtmmenu[Dap$v_Dtm_Edt]
THEN Dap$Put_Date (dd,.Edtdesc[Str$a_Pointer]); !Scratch date
END; !of code to send DATE & TIME message
!
! Send PROTECTION message if needed
!
IF .xabpro NEQ 0 ! If a protection XAB was given
AND .config[XAB$V_PROTECTION] ! and supported on the remote
AND .display[DAP$V_DISPLAY_PRO] ! And it was asked for
THEN BEGIN ! Send PROTECTION message if needed
LOCAL promenu : BITVECTOR[42] INITIAL(0),
vprotsys, ! System protection bitvector
vprotown, ! Owner protection bitvector
vprotgrp, ! Group protection bitvector
vprotwld; ! World protection bitvector
%IF %DECLARED (XABPRO$A_OWNER) ! If ever there is an owner string
%THEN LOCAL owner : BYTE8VECTOR[40] INITIAL(0);
%FI
INIT_MESSAGE (dd); ! Start building the message
! Remember that DAP$PUT_BITVECTOR and DAP$SIZE_BITVECTOR want an
! address of the bitvector, not the value of the bitvector, so move
! the bitvectors out of the XAB and into local storage.
vprotsys = .xabpro[XAB$V_PROTSYS]; ! System
vprotown = .xabpro[XAB$V_PROTOWN]; ! Owner
vprotgrp = .xabpro[XAB$V_PROTGRP]; ! Group
vprotwld = .xabpro[XAB$V_PROTWLD]; ! World
! Compute the length of the message
dd[DAP$H_LENGTH]= ! Compute length of the message
(1 ! The menu is 1 byte long
%IF %DECLARED (XABPRO$A_OWNER)
%THEN ! This code is for illustration only
+(IF (.owner[0] NEQ 0)
THEN (promenu[Dap$v_ProtMenu_Owner]=1;.owner[0]+1)
ELSE 0)
%FI
+ DAP$SIZE_BITVECTOR (vprotsys,3,1)
+ DAP$SIZE_BITVECTOR (vprotown,3,1)
+ DAP$SIZE_BITVECTOR (vprotgrp,3,1)
+ DAP$SIZE_BITVECTOR (vprotwld,3,1));
! Turn on menu bits for each part of the protection we offer.
promenu[DAP$V_PROTMENU_PROTSYS] = ! System
promenu[DAP$V_PROTMENU_PROTOWN] = ! Owner
promenu[DAP$V_PROTMENU_PROTGRP] = ! Group
promenu[DAP$V_PROTMENU_PROTWLD] = 1; ! World
! Send out the header and then bitvectors for each protection field.
dd[DAP$B_OPERATOR] = DAP$K_PROTECTION; ! Message type
dd[DAP$V_MFLAGS_LENGTH] = 1; ! Length field present
DAP$PUT_HEADER (dd); ! Put header there
DAP$PUT_BITVECTOR (dd, promenu, 6); ! Protection menu
%IF %DECLARED (XABPRO$A_OWNER) ! If ever there will be owner string
%THEN ! This code is for illustration only
IF .promenu[DAP$V_PROTMENU_OWNER] ! OWNER string - not used here
THEN DAP$PUT_VARIABLE_COUNTED (dd, CH$PTR(owner,0,8));
%FI
DAP$PUT_BITVECTOR (dd, vprotsys, 3); ! System
DAP$PUT_BITVECTOR (dd, vprotown, 3); ! Owner
DAP$PUT_BITVECTOR (dd, vprotgrp, 3); ! Group
DAP$PUT_BITVECTOR (dd, vprotwld, 3); ! World
END; ! code to send PROTECTION message
!
! Send SUMMARY message if needed
!
IF .xabsum NEQ 0 ! If a Summary XAB was given
AND .Config[Xab$v_Summary] ! and supported on the remote
AND .Display[Dap$v_Display_Sum]
THEN
BEGIN !Send Summary message if needed
LOCAL SumMenu: BITVECTOR[42];
Clearv (SumMenu);
Init_Message (dd);
dd[Dap$b_Operator]=Dap$k_Summary; !Message type
dd[Dap$v_Mflags_Length]=1; !Length field present
SumMenu[Dap$v_SumMenu_NoK]=1;
SumMenu[Dap$v_SumMenu_NoA]=1;
dd[Dap$h_Length]=
1 !The menu is 1 byte long
+.SumMenu[Dap$v_SumMenu_Nok]
+.SumMenu[Dap$v_SumMenu_NoA];
Dap$Put_Header (dd);
Dap$Put_Bitvector (dd, SumMenu, 6); !Menu
IF .SumMenu[Dap$v_SumMenu_NoK] ! NOK field
THEN Dap$Put_Byte (dd, .XabSum[Xab$b_NoK]);
IF .SumMenu[Dap$v_SumMenu_NoA] ! NOA field
THEN Dap$Put_Byte (dd, .XabSum[Xab$b_NoA]);
%BLISS32( ! Not in RMS-20 or RMS-11
IF .SumMenu[Dap$v_SumMenu_NoR] ! NOR field
THEN Dap$Put_Byte (dd, .XabSum[Xab$b_NoR]);
IF .SumMenu[Dap$v_SumMenu_PVn] ! PVN field
THEN Dap$Put_Byte (dd, .XabSum[Xab$b_PVn]);
) ! End of non-20 code
END; !of code to send SUMMARY message
!
! Send KEY DEFINITION messages if needed
!
IF .Config[Xab$v_Key_Definition] ! If supported on the remote
AND .Display[Dap$v_Display_Key] ! And user wanted it !m513
THEN INCR Krf FROM 0 TO 255 ! For each KEY DEFINITION XAB given
DO
BEGIN
LOCAL KeyMenu: BITVECTOR[42] INITIAL(0);
LOCAL NSg;
LOCAL Knmlen: INITIAL(0);
LOCAL Dtp,
Flg: BITVECTOR[21] INITIAL(0);
BIND KeyXab=UAddr(.XabKey[.Krf]): $XabKey_decl; !m515
IF KeyXab EQL 0 THEN EXITLOOP; ! No more keys
Clearv (KeyMenu,Flg);
Init_Message (dd);
dd[Dap$b_Operator]=Dap$k_Key; !Message type
dd[Dap$v_Mflags_Length]=1; !Length field present
Flg[Dap$v_Flg_Dup] = .KeyXab[Xab$v_Dup];
Flg[Dap$v_Flg_Chg] = .KeyXab[Xab$v_Chg];
IF .Flg NEQ 0
THEN KeyMenu[Dap$v_KeyMenu_Flg]=1;
IF .KeyXab[Xab$h_Dfl] NEQ 0
THEN KeyMenu[Dap$v_KeyMenu_DFl]=1;
IF .KeyXab[Xab$h_Ifl] NEQ 0
THEN KeyMenu[Dap$v_KeyMenu_IFl]=1;
KeyMenu[Dap$v_KeyMenu_Ref]=1;
!+ 610
! If there is a KeyName field, set the menu flag, convert the
! user's XAB KNM text into counted ASCII, and calculate the length
! of the DAP field as <length of text>+1 byte for the count.
! Note that if we are sending returned post-access attributes we
! may have a Knm pointer field which points to a null Knm text (there
! was no Knm for this key). Set the menu flag anyway, even with
! a text field length of zero: this way the receiver's Knm pointer
! will get properly updated to point to a null text string, indicating
! the absence of the field in the file being accessed.
!-
IF .KeyXab[Xab$a_Knm] NEQ 0
THEN
BEGIN
KeyMenu[Dap$v_KeyMenu_Knm]=1;
Knmlen = Chazac ( UAPointer(.KeyXab[Xab$a_Knm]),
CH$PTR(BufKnm,0,7))+1;
END;
IF .KeyXab[Xab$b_Ian] NEQ 0
THEN KeyMenu[Dap$v_KeyMenu_IAn]=1;
IF .KeyXab[Xab$b_Dan] NEQ 0
THEN KeyMenu[Dap$v_KeyMenu_DAn]=1;
%BLISS36(
! Count segments, and check the size of each.
! If a segment is over 255 bytes long, DAP won't hack it
NSg=( LOCAL ks;
LABEL CntSeg;
CntSeg:( INCR i FROM 0 TO 7
DO IF (ks = .KeyXab[.i+%FIELDEXPAND(Xab$h_Siz0)]) EQL 0
THEN LEAVE CntSeg WITH .i
ELSE IF .ks GTR 255 THEN UserError( RMS$_SIZ ) ;
8 ) ); ! If none are zero, must be 8, the max !m606
! The above depends on the fact that each Pos/Siz pair is 1 word long
)
%BLISS32( the above will not work on VMS )
Dtp=$Value_Rms_Dap( .KeyXab[Xab$v_Dtp], Xab$k_, Dap$k_Dtp_, Rms$_Dtp,
Stg, %(In2, Bn2,)% In4, Bn4, Pac, In8, %(Bn8)% );
IF .Dtp NEQ 0
THEN KeyMenu[Dap$v_KeyMenu_Dtp]=1;
!+ 610
! Number of segments is always at least 1, since a non-byte-oriented
! key datatype may have defaulted its size to zero.
!-
KeyMenu[Dap$v_KeyMenu_NSg] = 1;
IF .NSg EQL 0 THEN NSg = 1;
dd[Dap$h_Length]=
Dap$Size_Bitvector( Keymenu, 6, 1) ! menu may be longer !m545
+.KeyMenu[Dap$v_Keymenu_Flg]
+.KeyMenu[Dap$v_KeyMenu_DFl]*2
+.KeyMenu[Dap$v_KeyMenu_IFl]*2
+.KeyMenu[Dap$v_KeyMenu_NSg]*(1+(.NSg*3)) !m572
+.KeyMenu[Dap$v_KeyMenu_Ref]
+.Knmlen !610
+.KeyMenu[Dap$v_KeyMenu_Dtp]
+.KeyMenu[Dap$v_KeyMenu_IAn]
+.KeyMenu[Dap$v_KeyMenu_DAn];
! Includes a 2-byte POS field & a 1-byte SIZ field per segment
Dap$Put_Header (dd);
Dap$Put_Bitvector (dd, KeyMenu, 6); !Menu
IF .KeyMenu[Dap$v_KeyMenu_Flg] ! FLG field
THEN Dap$Put_Bitvector (dd, Flg, 3);
IF .KeyMenu[Dap$v_KeyMenu_DFl] ! DFL field
THEN Dap$Put_2Byte (dd, .KeyXab[Xab$h_DFl]);
IF .KeyMenu[Dap$v_KeyMenu_IFl] ! IFL field
THEN Dap$Put_2Byte (dd, .KeyXab[Xab$h_IFl]);
IF .KeyMenu[Dap$v_KeyMenu_NSg] ! NSG, POS, SIZ fields
THEN
BEGIN
Dap$Put_Byte (dd, .NSg); ! Send number of segments
INCR i FROM 0 TO .NSg-1
DO
BEGIN
%BLISS36(
BIND xseg=KeyXab+.i: $XabKey_decl;
! This depends on the fact that a POS/SIZ pair is 1 word
Dap$Put_2Byte( dd, .xseg[Xab$h_Pos0] );
Dap$Put_Byte( dd, .xseg[Xab$h_Siz0] );
)
END;
END;
IF .KeyMenu[Dap$v_KeyMenu_Ref] ! REF field
THEN Dap$Put_Byte (dd, .KeyXab[Xab$b_Ref]);
IF .KeyMenu[Dap$v_KeyMenu_Knm] ! KNM field !610
THEN Dap$Put_Variable_Counted (dd, CH$PTR(BufKnm,0,7));
IF .KeyMenu[Dap$v_KeyMenu_IAn] ! IAN field
THEN Dap$Put_Byte (dd, .KeyXab[Xab$b_IAn]);
!d610
IF .KeyMenu[Dap$v_KeyMenu_LAn] ! LAN field
THEN Dap$Put_Byte (dd, .KeyXab[Xab$b_LAn]);
IF .KeyMenu[Dap$v_KeyMenu_DAn] ! DAN field
THEN Dap$Put_Byte (dd, .KeyXab[Xab$b_DAn]);
IF .KeyMenu[Dap$v_KeyMenu_DTp] ! DTP field
THEN Dap$Put_Byte (dd, .Dtp); !610
END; !of code to send KEY DEFINITION message
!
! Send ALLOCATION messages if needed
!
IF .Config[Xab$v_Allocation] ! If supported on the remote
AND .Display[Dap$v_Display_All] ! And user wanted it !m513
THEN INCR AId FROM 0 TO 31 ! For each ALLOCATION XAB given
DO
BEGIN
LOCAL AllMenu: BITVECTOR[42];
Bind AllXab=.XabAll[.AId]: $XabAll_decl;
IF AllXab EQL 0 THEN EXITLOOP; ! No more Areas
Clearv (AllMenu);
Init_Message (dd);
dd[Dap$b_Operator]=Dap$k_Allocation; !Message type
dd[Dap$v_Mflags_Length]=1; !Length field present
AllMenu[Dap$v_AllMenu_AId]=1;
AllMenu[Dap$v_AllMenu_BKz]=1;
dd[Dap$h_Length]=
Dap$Size_Bitvector( Allmenu, 6, 1) ! menu may be longer !m545
+.AllMenu[Dap$v_AllMenu_AId]
+.AllMenu[Dap$v_AllMenu_BKz];
Dap$Put_Header (dd);
Dap$Put_Bitvector (dd, AllMenu, 6); !Menu
IF .AllMenu[Dap$v_AllMenu_AId] ! AID field
THEN Dap$Put_Byte (dd, .AllXab[Xab$b_AId]);
IF .AllMenu[Dap$v_AllMenu_BKz] ! BKZ field
THEN Dap$Put_Byte (dd, .AllXab[Xab$b_BKz]);
END; !of code to send ALLOCATION messages
!+
! Send Resultant File Name if requested
!-
IF .Display[Dap$v_Display_Name]
THEN Dap$Put_Name( dd, Fab, %REF(1^Dap$k_Nametype_Fsp) );
END; !DAP$PUT_ATTRIBUTES
GLOBAL ROUTINE Dap$Put_Access (P_Dd: REF $Dap_Descriptor,
P_Fab: REF $Fab_Decl,
Accfunc,
P_Accopt: REF BITVECTOR,
P_Display: REF BITVECTOR,
P_NFab: REF $Fab_Decl ): NOVALUE=
BEGIN
!++
! FUNCTIONAL DESCRIPTION:
!
! build ACCESS message & put in output buffer
!
! FORMAL PARAMETERS:
!
! P_DD: Address of DAP descriptor
! P_FAB: " " RMS FAB
! ACCFUNC: Access Function to perform
! P_ACCOPT: Access option bits (DAP)
! P_DISPLAY: Display Bits (DAP)
! P_NFAB: FAB with New name for rename
!
! IMPLICIT OUTPUTS:
!
! An ACCESS msg will be put in the output buffer
!
! ROUTINE VALUE:
!
! NONE
!
! SIDE EFFECTS:
!
! NONE
!
!--
BIND dd=.P_dd: $Dap_Descriptor,
Fab=.p_Fab: $Fab_Decl,
Nfab=.p_Nfab: REF $Fab_Decl,
Accopt=.p_Accopt: BITVECTOR,
Display=.p_Display: BITVECTOR;
BIND Nam=UAddr(.Fab[Fab$a_Nam]): $Nam_Decl; ! Name block (if any) !m507
LOCAL
nptr,
nlen,
fac: BITVECTOR[21],
shr: BITVECTOR[21],
filedesc: $Str_Descriptor(Class=Bounded),
rfiledesc: $Str_Descriptor(Class=Dynamic);
CLEARV (fac,shr);
Init_Message (dd);
dd[Dap$b_Operator]=Dap$k_Access;
dd[Dap$v_Mflags_Length]=1; ! Length field present always
!Make sure we request enough access to do what we want
CASE .accfunc FROM Dap$k_Open TO Dap$k_Accfunc_Max OF
SET
[Dap$k_Open]: Fab[Fab$v_Get]=1; !Ask for GET access
[Dap$k_Create,
Dap$k_Submit]: Fab[Fab$v_Put]=1; !Ask for PUT access
[INRANGE]: ; ! Not needed
[OUTRANGE]: SIGNAL (Dap$_Aor, dd);
TES;
!+
! Massage RMS FAC and SHR bits into DAP bitvectors
!-
$Dap_Move_Bits (Fab, Fab$v_, fac, Dap$v_Fac_, ! FAC
Get,Put,Del,Bio,Trn,Upd,Bro,App);
$Dap_Move_Bits (Fab, Fab$v_Shr, shr, Dap$v_Fac_,
Get,Put,Del,Bio,Upd,Bro); ! SHR
!? We will ignore the multi-stream access bit for now
! If we have a resultant name string, use it.
! If not, try expanded name string.
! If we have neither of those, or no name block at all, use the original string
IF nam NEQ 0
THEN
BEGIN
IF .Nam[Nam$h_Esl] NEQ 0
THEN
BEGIN
nptr=UAPointer(.Nam[Nam$a_Esa]);
nlen=.Nam[Nam$h_Esl];
END
ELSE
BEGIN
nptr=UAPointer(.Fab[Fab$a_Fna]);
nlen=Asciz_Len(.nptr);
END;
END
ELSE
BEGIN
nptr=UAPointer(.Fab[Fab$a_Fna]);
nlen=Asciz_Len(.nptr);
END;
$Str_Desc_Init ( Desc=filedesc,
String=(.nlen, .nptr),
Class=Bounded );
!
! Scan off nodeid and remove access info if any
!
![22] vv
!
! Use the remainder string
!
IF $Str_Scan ( Remainder=filedesc, Find='::', ! Strip up to ::
Substring=filedesc ) ! since we will use remainder
THEN
BEGIN
LOCAL
ptr,
ch;
filedesc[str$h_pfxlen]=.filedesc[str$h_pfxlen]+2;
filedesc[str$a_pointer]= CH$PLUS(.filedesc[str$a_pointer], 2);
filedesc[str$h_length]=.filedesc[str$h_maxlen]-.filedesc[str$h_pfxlen];
! Strip ;USERID ;PASSWORD ;CHARGE (and ;Pnnnnn)
ptr=.filedesc[Str$a_Pointer];
INCR i FROM 0 TO .filedesc[Str$h_Length] DO
BEGIN
IF CH$RCHAR_A(ptr) EQL %c';'
THEN SELECT CH$RCHAR(.ptr) AND %O'137' OF
SET ! Uppercase and compare
[%C'U', %C'P', %C'C']:
BEGIN
filedesc[Str$h_Length] = .i;
EXITLOOP;
END;
TES;
END;
END
ELSE
Filedesc[Str$h_Length] = .Filedesc[Str$h_MaxLen];
! Make the REMAINDER be the STRING
! Make a copy of the string
$Str_Desc_Init ( Desc=rfiledesc, Class=Dynamic );
$Str_Copy ( String=filedesc, Target=rfiledesc );
! Strip ^V
!?SOMEDAY
%(
IF .d$gtrace[1] ! For Debugging
THEN $Xpo_Put_Msg ( String=$Str_Concat('Remote File:',rfiledesc),
Severity=Success );
)%
!Find out how long the message will be (and build a few fields in the process)
dd[Dap$h_Length]=(1 !Length so far=1
+ $Dap_Size_Bitvector (accopt, 5) ! +# of bytes of ACCOPT
+ .rfiledesc[str$h_length] + 1 ! [22] ^^
!Add length of the file name +1 for count byte
+$Dap_Size_Bitvector (fac, 3,
shr, 3,
display, 4)
);
!Now build the message a field at a time
Dap$Put_Header (dd); ! First, the message header
Dap$Put_Byte (dd, .Accfunc); !Access function
Dap$Put_Bitvector (dd, Accopt, 5); !Access options
Dap$Put_Byte (dd, .rfiledesc[Str$h_Length]); !Length of remote filespec
Dap$Put_String (dd, rfiledesc); !Remote file spec ![22]
Dap$Put_Bitvector (dd, fac, 3); !FAC
Dap$Put_Bitvector (dd, shr, 3); !SHR
Dap$Put_Bitvector (dd, display, 4); !DISPLAY
IF .Accfunc EQL Dap$k_Rename
THEN
BEGIN ! [4] Pass address of bitvector
LOCAL nametype: BITVECTOR[24] PRESET([Dap$k_Nametype_Fsp]=1);
Dap$Put_Name (dd, Nfab, Nametype); ! New name for rename
END;
$Xpo_Free_Mem ( String=rfiledesc); ! Free filename now [22]
END; !Dap$Put_Access
GLOBAL ROUTINE Dap$Put_name (P_Dd: REF $Dap_Descriptor,
P_Fab: REF $Fab_Decl,
P_Name_Type: REF BITVECTOR): NOVALUE=
BEGIN
!++
! FUNCTIONAL DESCRIPTION:
!
! Send a NAME message
!
! FORMAL PARAMETERS:
!
! P_DD: addr of DAP descriptor
! P_FAB: addr of RMS FAB
! P_NAME_TYPE: name type (DAP) address of bitvector
!--
BIND
dd=.P_dd: $Dap_Descriptor,
fab=.p_fab: $Fab_Decl,
Nam=UAddr(.Fab[Fab$a_Nam]): $Nam_decl,
Name_type=.P_Name_Type: BITVECTOR;
LOCAL
ptr,
filedesc: $Str_descriptor();
$Str_Desc_Init( Desc=filedesc );
SELECT 1 OF
SET
[ .Name_Type[Dap$k_Nametype_Fsp] ]:
BEGIN
IF Nam NEQ 0
THEN
BEGIN
IF .Nam[Nam$h_Rsl] NEQ 0
THEN $Str_Desc_Init( Desc=Filedesc,
String=(.Nam[Nam$h_Rsl], .Nam[Nam$a_Rsa]) )
ELSE IF .Nam[Nam$h_Esl] NEQ 0
THEN $Str_Desc_Init( Desc=Filedesc,
String=(.Nam[Nam$h_Esl], .Nam[Nam$a_Esa]) );
END;
IF .Filedesc[Str$h_Length] EQL 0 ! Nothing yet
THEN
BEGIN
LOCAL tfiledesc: $Str_descriptor( Class=Bounded, String=(0,0) );
$Str_Desc_Init( Desc=filedesc,
String=Asciz_Str( (UAPointer( .Fab[Fab$a_Fna] ) ) ) ) ;
IF $Str_Scan( String=filedesc,
Find='::',
Substring=tfiledesc )
THEN $Str_Desc_Init( Desc=filedesc,
String=Str_Remainder( tfiledesc ) );
! Strip ;USERID ;PASSWORD ;CHARGE (and ;Pnnnnn)
ptr=.filedesc[Str$a_Pointer];
INCR i FROM 0 TO .filedesc[Str$h_Length] DO
BEGIN
IF CH$RCHAR_A(ptr) EQL %c';'
THEN SELECT CH$RCHAR(.ptr) AND %O'137' OF
SET ! Uppercase and compare
[%C'U', %C'P', %C'C']:
BEGIN
filedesc[Str$h_Length] = .i;
EXITLOOP;
END;
TES;
END;
END;
END;
[ .Name_Type[Dap$k_Nametype_Str] ]:
BEGIN
IF Nam EQL 0
THEN SIGNAL(Rms$_Nam); ! Nam block needed
$Str_Desc_Init( Desc=filedesc,
String=(.Nam[Nam$b_Dev], UAPointer(.Nam[Nam$a_Dev]) ) );
END;
[ .Name_Type[Dap$k_Nametype_Dir] ]:
BEGIN
IF Nam EQL 0
THEN SIGNAL(Rms$_Nam); ! Nam block needed
$Str_Desc_Init( Desc=filedesc,
String=(.Nam[Nam$b_Dir], UAPointer(.Nam[Nam$a_Dir]) ) );
END;
[ .Name_Type[Dap$k_Nametype_Nam] ]:
BEGIN
IF Nam EQL 0
THEN SIGNAL(Rms$_Nam); ! Nam block needed
$Str_Desc_Init( Desc=filedesc,
String=(.Nam[Nam$b_Name]+.Nam[Nam$b_Type]+.Nam[Nam$b_Ver],
UAPointer(.Nam[Nam$a_Name]) ) ); !m561
END;
TES;
Init_Message (dd);
dd[Dap$b_Operator]=Dap$k_Name;
dd[Dap$v_Mflags_Length]=1; !LENGTH field present
dd[Dap$h_Length] = $Dap_Size_Bitvector (Name_Type, 3)
+ .Filedesc[Str$h_Length] + 1;
! Length of message
! add 1 for count byte
Dap$Put_Header (dd);
Dap$Put_Bitvector (dd, Name_Type, 3); ! NAMETYPE field
Dap$Put_Byte( dd, .filedesc[Str$h_Length] ); ! Length byte
Dap$Put_String (dd, filedesc ); ! FILESPEC field
END;
GLOBAL ROUTINE Dap$Put_Control (P_Dd: REF $Dap_Descriptor,
P_Rab: REF $Rab_Decl,
Cfun,
P_Display: REF BITVECTOR) :NOVALUE=
BEGIN
!++
! FUNCTIONAL DESCRIPTION:
!
! Build CONTROL message
!
! FORMAL PARAMETERS:
!
! P_DD: Address of DAP descriptor
! P_RAB: Address of RMS RAB
! CFUN: Control message function code
! P_DISPLAY: Address of display bitvector
!
!--
LOCAL
dtp, ! Key datatype !a504
ctlmenu: BITVECTOR[7],
rac,
key: BYTE8VECTOR[255],
krf,
rop: BITVECTOR[42],
rop_size,
hsh: BITVECTOR[35],
hsh_size,
display_size;
BIND
dd=.p_dd: $Dap_Descriptor,
Rab=.P_Rab: $Rab_Decl,
Rst=.Rab[Rab$a_Isi]: $Rms_Rst, ! Bind the Fst !a557
Fab=UAddr(.Rab[Rab$a_Fab]): $Fab_Decl, ! Find our FAB !m506
Fst=.Fab[Fab$a_Ifi]: $Rms_Fst,
Config=.Fst[Fst$a_Config]: $XabCfg_decl,
Display=.P_Display: BITVECTOR;
Clearv (ctlmenu,key,krf,rop,hsh);
Init_Message (dd);
dd[Dap$b_Operator]=Dap$k_Control; ! This is a CONTROL message
dd[Dap$b_StreamId]=.Rst[Rst$v_StreamId];! Set up stream id !a557
dd[Dap$v_Mflags_Length]=1; ! Always a length field
Ctlmenu[Dap$v_Ctl_Rac]=1; ! Always have to send a RAC
rac=$Dap_Translate_Value (.Rab[Rab$b_Rac],
Rab$k_, Dap$k_Rac_,
Seq,Key,Rfa,Tra,Blk,Bft);
CASE .Rab[Rab$b_Rac] FROM Rab$k_Seq TO Rab$k_Bft OF
SET
[Rab$k_Seq]: ! See if FAL can hack it
IF NOT .config[xab$v_sequential_access]
THEN rac=Dap$k_Rac_Tra; ! It can't, use file xfer mode ![16]
[Rab$k_Tra]:;
[Rab$k_Blk, ! Block Mode
Rab$k_Bft]: ! Block mode file transfer
BEGIN
LOCAL keyval;
ctlmenu[Dap$v_Ctl_Key]=1; ! We will send the KEY
keyval=Rms_Vbn_to_Dap (.Rab[Rab$g_Bkt]);
key[0]=%BPVAL/8; ! Key is converted bucket number
INCR i FROM 1 TO %BPVAL/8 !
DO (key[.i]=.keyval; keyval=.keyval^-8);
END;
[Rab$k_Rfa]: ! RFA access
BEGIN
ctlmenu[Dap$v_Ctl_Key]=1; ! We will send the KEY
Dap$Rfa_Rms_Dap( .Rab[Rab$g_Rfa], key ); ! Make RFA to suit remote !m605
END;
[Rab$k_Key]: ! Key access
BEGIN
ctlmenu[Dap$v_Ctl_Key]=1; ! We will send the key
SELECT .Fab[Fab$v_Org] OF
SET
[Fab$k_Rel]: ! Relative file
dtp = Xab$k_Bn4; !
[Fab$k_Idx]: ! Indexed file
BEGIN
LOCAL thiskdb: REF $Rms_Kdb;
thiskdb=.Fst[Fst$a_Kdb];
dtp=0;
WHILE .thiskdb NEQ 0 ! 620
DO
IF (.thiskdb[kdb$h_Reference] EQL .Rab[Rab$b_Krf])
THEN EXITLOOP ( dtp = .thiskdb[kdb$v_datatype] )
ELSE thiskdb=.thiskdb[kdb$a_nxt];
krf = .thiskdb[kdb$h_Reference]; ! 620
Ctlmenu[Dap$v_Ctl_Krf] = 1; ! 620
END;
TES;
CASE .dtp FROM Xab$k_Stg TO Xab$k_Bn4 OF
SET
[Xab$k_In4, Xab$k_Bn4]:
! KBF is address of record number
! Get value of key from user section
BEGIN ! Key is Record number or other integer
LOCAL keyval; ! KBF is address of record number
keyval=.( UAddr( .Rab[Rab$a_Kbf] ) ); ! get word from user sect !m555
key[0]=%BPVAL/8;
INCR i FROM 1 TO %BPVAL/8
DO (key[.i]=.keyval; keyval=.keyval^-8)
END;
[Xab$k_Stg, Xab$k_Ebc, Xab$k_Pac]:
BEGIN ! Key is a string
LOCAL Keyptr;
Key[0]=.rab[Rab$b_Ksz]; ! KSZ is length of string
Keyptr=.rab[Rab$a_Kbf]; ! Character pointer to key
TGUPointer( Keyptr, .Fst[Fst$h_Bsz] ); ! Make byte pointer !623
INCR i FROM 1 TO .key[0] ! Copy the string
Do (Key[.i]=CH$RCHAR_A(Keyptr));! !623
END;
[INRANGE, OUTRANGE]: SIGNAL( Rms$_Ons ); ! Not supported
TES;
END;
[OUTRANGE]: SIGNAL( Rms$_Rac );
TES;
$Dap_Move_Bits (Rab, Rab$v_, Rop, Dap$v_Rop_,
Eof,Fdl,Uif,Hsh,Loa,Ulk,Tpt,
Rah,Wbh,Kge,Kgt,Nlk,Rlk,Bio,
Lim,Nxr); ! Translate the RMS ROP to a DAP one
Rop_Size=Dap$Size_Bitvector(Rop,6,0); ! Remember the size of this now
IF .rop_Size NEQ 0 THEN Ctlmenu[Dap$v_Ctl_Rop]=1; !Remember to send if needed
!HSH is reserved as of DAP 7.0
HSH_SIZE=0;
! Calculate the size of display bitvector now
Display_Size = Dap$Size_Bitvector (display,4,0); !m571
IF .display_Size NEQ 0 THEN Ctlmenu[Dap$v_Ctl_Display]=1; ! send if needed
Dd[Dap$h_Length]=(1 ! Length of CTLFUNC
+Dap$Size_Bitvector (Ctlmenu,4,0) ! Length of menu
+.ctlmenu[Dap$v_Ctl_Rac] ! Length of RAC
+(IF .ctlmenu[Dap$v_Ctl_Key]
THEN .key[0]+1 ELSE 0) ! Length of KEY
+(.ctlmenu[Dap$v_Ctl_Krf]) ! Length of KRF = 1
+.rop_Size ! Length of ROP
+.hsh_Size ! Length of HSH
+.display_Size ! Length of DISPLAY
);
Dap$Put_Header (dd); ! Send the header
Dap$Put_Byte (dd, .Cfun); !Function code
Dap$Put_Bitvector (dd, ctlmenu, 4); !Send the menu
IF .ctlmenu[Dap$v_Ctl_Rac] !RAC field
THEN Dap$Put_Byte (dd, .rac); !
IF .ctlmenu[Dap$v_Ctl_Key] !Key field
THEN DAP$Put_Variable_Counted (dd, CH$PTR(key,0,8) );
IF .ctlmenu[Dap$v_Ctl_Krf]
THEN Dap$Put_Byte (dd, .krf); ! KRF field
IF .ctlmenu[Dap$v_Ctl_Rop]
THEN Dap$Put_Bitvector (dd, rop, 6); ! ROP field
IF .ctlmenu[Dap$v_Ctl_Hsh]
THEN Dap$Put_Bitvector (dd, hsh, 5); ! HSH field
IF .ctlmenu[Dap$v_Ctl_Display]
THEN Dap$Put_Bitvector (dd, display, 4); ! DISPLAY field
END; !Dap$Put_Control
GLOBAL ROUTINE Dap$Get_Status ( P_DD: REF $Dap_Descriptor )=
BEGIN
!++
! FUNCTIONAL DESCRIPTION:
!
! Routine to process a STATUS message
! Note that the message header must have already been eaten
! Signals error condition & returns code
!
! FORMAL PARAMETERS:
!
! P_DD: Addr of DAP descriptor
!
! IMPLICIT OUTPUTS:
!
! Fst[Fst$v_Error] is set or cleared
! Rab[Rab$g_Rfa] and Rst[Rst$g_Data_Rfa]
! are filled in if an RFA is given in the message
!
! COMPLETION CODES:
!
! System-dependent error code (but we SIGNAL first)
!
! SIDE EFFECTS:
!
! SIGNALs error if the status message indicates one.
!
!--
BIND dd=.p_dd: $Dap_Descriptor;
LOCAL
code;
OWN
rfa: BYTE8VECTOR[9],
recnum: BYTE8VECTOR[9],
stv: BYTE8VECTOR[9];
! Clearv (rfa,recnum,stv);
code=DAP$Get_2byte (dd); !Put maccode+miccode here
SELECT (.code AND Dap$m_Maccode) OF !m577
SET
[Dap$k_Mac_Open]:
Fst[Fst$v_File_Open] = 0;
[Dap$k_Mac_Invalid, ! Protocol Errors do not leave us
Dap$k_Mac_Sync]: ! with a useable access.
Fst[Fst$v_File_Open] ! Usually get this when we get an
= .Fst[Fst$v_Access_Active] ! error and try to skip to a
= 0; ! possible next file.
TES;
IF .dd[Dap$h_Length] GTR 0 ! Get the RFA (up to 8 bytes) [20]
THEN
BEGIN
Dap$Get_Variable_Counted (dd, CH$PTR(rfa,0,8), 8);
IF (.rfa[0] GTR 0) ! Return RFA to user if given !m605
AND (.Rab NEQ 0) ! Provided we have a place to put it
THEN Rab[Rab$g_Rfa] = Rst[Rst$g_Data_Rfa] =Dap$Rfa_Dap_Rms( rfa );
END;
IF .dd[Dap$h_Length] GTR 0 ! Get the RECNUM (up to 8 bytes) [20]
THEN Dap$Get_Variable_Counted (dd, CH$PTR(recnum,0,8), 8); !m561
IF .dd[Dap$h_Length] GTR 0 ! Get the STV (up to 8 bytes) [20]
THEN Dap$Get_Variable_Counted (dd, CH$PTR(stv,0,8), 8); !m561
!
! If we were trying to bail out and remote complains
! we must not have had an active access to begin with
!
IF ( .Code EQL ( Dap$k_Mac_Sync + Dap$k_Access_Complete ) ) !a577
THEN Fst[Fst$v_File_Open] = Fst[Fst$v_Access_Active] = 0; !a577
!
! Ignore errors about CONTINUE or ACCESS COMPLETE
! if we were trying to bail out of an error
!
IF ( .Code EQL ( Dap$k_Mac_Invalid + Dap$k_Mic_Continue + %O'20' ) )
OR ( .Code EQL ( Dap$k_Mac_Sync + Dap$k_Access_Complete ) ) !m577
OR ( .Code EQL ( Dap$k_Mac_Sync + Dap$k_Continue ) ) !m606
THEN IF .Fst[Fst$v_Error] !m577
THEN RETURN .UsrStv; ! Propegate previous error code
UsrStv = .Code; ! Return maccode+micccode as STV !m566
UsrSts = Dap$Error_Dap_Rms( .Code ); ! Make RMS code !m566
SELECTONE .UsrSts OF
SET
[Rms$k_Suc_Min TO Rms$k_Suc_Max]:
Fst[Fst$v_Error]=0; ! Else clear error flag
[Rms$_Eof]: ! End-of-file is different
SIGNAL( .UsrSts, .UsrStv ); ! Signal it
[Rms$k_Err_Min TO Rms$k_Err_Max]: ! If we got an error
BEGIN
Fst[Fst$v_Error]=1; ! Set error flag
SIGNAL( .UsrSts, .UsrStv ) ! Signal it
END;
TES;
.Stv ! Return DAP status code
END; !Dap$Get_Status
GLOBAL ROUTINE Dap$Get_Ack ( P_Dd: REF $Dap_Descriptor )=
BEGIN
!++
! FUNCTIONAL DESCRIPTION:
!
! Routine to expect and process an ACK message,
! or a STATUS message if we aren't lucky
!
! FORMAL PARAMETERS:
!
! DD: Addr of DAP descriptor
!
! IMPLICIT INPUTS:
!
! Input buffer & pipeline
!
! IMPLICIT OUTPUTS:
!
! Fst[Fst$v_Error] is set if error, cleared if not
!
! COMPLETION CODES:
!
! STS$K_NORMAL if we get an ACK,
! error code otherwise
!
!--
BIND dd=.P_Dd: $Dap_Descriptor;
SELECT Dap$Get_Header (dd)
OF SET
[Dap$k_Ack]:
BEGIN
Fst[Fst$v_Error]=0; ! Not an error
STS$K_NORMAL
END;
[Dap$k_Status]: Dap$Get_Status (dd);
[OTHERWISE]: SIGNAL (Dap$_Sync, dd);
TES
END; !DAP$GET_ACK
GLOBAL ROUTINE Dap$Rfa_Rms_Dap( rfanum, pbv: REF Byte8Vector[8] ) : NOVALUE =
!+
! Make an RFA into an image field for DAP
! If it is negative, the sign bit was a flag to reformat it to
! a 6-byte VMS indexed file RFA:
!
! +-+------------------------+--------------------------------------------+
! |1| record within bucket | bucket number |
! +-+------------------------+--------------------------------------------+
! 1 11 24
!-
BEGIN !a605v
IF .Rab[Rab$g_Rfa] GEQ 0
THEN
BEGIN
LOCAL keyval: INITIAL(.rfanum);
pbv[0]=%BPVAL/8; ! Key is converted bucket number
INCR i FROM 1 TO %BPVAL/8 !
DO (pbv[.i]=.keyval; keyval=.keyval^-8);
END
ELSE ! Special case for VMS 6-byte RFAs
BEGIN
pbv[0]=6; ! Length of field
pbv[1]=.rfanum; ! Low-order 8 bits of VBN first
pbv[2]=.rfanum<8,8>; ! Next 8 bits of VBN
pbv[3]=.rfanum<16,8>; ! Next 8 bits of VBN
pbv[4]=0; ! If we get a VBN over 24 bits, too bad
pbv[5]=.rfanum<24,8>; ! Number within record
pbv[6]=.rfanum<32,3>; ! Last 3 bits
END;
END;
GLOBAL ROUTINE Dap$Rfa_Dap_Rms ( pbv: REF Byte8Vector ) =
BEGIN
LOCAL val: INITIAL(0);
IF .pbv[0] LSS 6
THEN
INCR i FROM 1 TO .pbv[0]
DO val = .val + ( .pbv[.i] ^ ( (.i-1) * 8 ) )
ELSE
BEGIN
val=.pbv[1];
val<8,8>=.pbv[2];
val<16,8>=.pbv[3];
val<24,8>=.pbv[5];
val<32,3>=.pbv[6];
val<35,1>=1; ! Flag for this kind of RFA
END;
.val ! Return as value
END; !a605^
END ELUDOM