Trailing-Edge
-
PDP-10 Archives
-
BB-JF18A-BM
-
sources/rms/rmsm11.b36
There are 3 other files named rmsm11.b36 in the archive. Click here to see a list.
MODULE M11FIL ( ! MACY11 file service for RMS
IDENT = '2',
ENTRY(
DoGetM11, ! Get a record from macy11 file
GetM11, ! Get a record from macy11 file
FndM11, ! Find a record in macy11 file
PutM11, ! Put a record to macy11 file
CncM11, ! Connect RAB to FAB for MACY11
DscM11 ! Close MACY11 file
)
) =
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: DAP
!
! ABSTRACT: Routines to transfer records or blocks of file data.
! Process MACY11 files
!
! ENVIRONMENT:
!
! AUTHOR: Andrew Nourse, CREATION DATE: 3-Mar-82
!
! 02 - Put in ENTRY points
! 01 - The beginning
!--
!
! INCLUDE FILES:
!
REQUIRE 'RMSREQ';
REQUIRE 'RMSOSD';
!
! TABLE OF CONTENTS:
!
FORWARD ROUTINE
DoGetM11 : NOVALUE, ! Get a record from macy11 file
GetM11, ! Get a record from macy11 file
FndM11, ! Find a record in macy11 file
PutM11: NOVALUE, ! Put a record to macy11 file
M11GBY, ! Get a byte from MACY11 file
M11PBY: NOVALUE, ! Put a byte to MACY11 file
CncM11: NOVALUE, ! Connect RAB to FAB for MACY11
DscM11: NOVALUE; ! Close MACY11 file
!
! MACROS:
!
MACRO Saved_Byte=Rst$h_Record_Size_Words %;
KEYWORDMACRO
Get_Bucket(Bucket,Bucket_Size=1,Lock=0,Desc)=
IF NOT Getbkt(Bucket,Bucket_Size,Lock,Desc)
THEN SIGNAL (Rms$_Rnf, 0, Rab[0,0,0,0] ) %,
Put_Bucket(Desc,Update=1)=
Putbkt(Update,Desc) %;
MACRO Free_Bucket[]=Put_Bucket(%remaining,Update=0) %;
MACRO Copy(From_Addr, To_Addr, Size)= ! Copy a block of memory
(REGISTER
tmpac1 = 6,
tmpac2 = 7,
tmpac3 = %O'10';
IF .RmsSec NEQ 0 ! If not in section 0
THEN
BEGIN
BIND
extend_block = UPLIT (Ext$k_Xblt^27); !m511
tmpac1 = size;
tmpac2 = from_addr;
tmpac3 = to_addr;
IF .tmpac2<18, 18> EQL 0 THEN tmpac2 = .tmpac2 OR .rmssec;
IF .tmpac3<18, 18> EQL 0 THEN tmpac3 = .tmpac3 OR .rmssec;
$extend_inst (tmpac1, extend_block)
END
ELSE
BEGIN
TmpAc1<Lh>=(From_Addr); ! FROM_ADDR is source addr
TmpAc1<Rh>=(To_Addr); ! TO_ADDR is destination addr
Blt(TmpAc1,((To_Addr)+(Size)-1)) ! SIZE is length of block
END ) %;
!
! EQUATED SYMBOLS:
!
LITERAL No_Byte=%O'777777';
LITERAL End_Of_Page_Mask=%O'770000000777';
!
! OWN STORAGE:
!
!
! EXTERNAL REFERENCES:
!
%IF %SWITCHES(TOPS20)
%THEN
EXTERNAL ROUTINE
WBucket;
%FI;
GLOBAL ROUTINE DoGetM11 : NOVALUE = ! Get a MACY11 record
!++
! FUNCTIONAL DESCRIPTION:
!
! Get a record from an open MACY11 file.
!
! IMPLICIT PARAMETERS:
!
! RAB: A RAB as defined by RMS
!
! COMPLETION CODES:
!
! Standard RMS codes
!
! SIDE EFFECTS:
!
! NONE
!
!--
BEGIN
TRACE ('DOGETASCII');
!+
! IF THE LAST OPERATION WAS NOT A $FIND, THEN WE
! MUST INSURE THAT WE ARE POSITIONED AT THE CORRECT
! RECORD. IF THE LAST OPERATION WAS A $FIND, THEN WE
! ARE ALREADY AT THE TARGET RECORD.
!-
IF .rst [rstlastoper] NEQ c$find THEN fndm11 ();
!+
! MOVE THE RECORD AND SET UP THE USER'S RSZ FIELD
!-
rab [rabrsz, 0] = getm11 (true); ! MOVE THE DATA
RETURN
END; !End of DOGETM11
GLOBAL ROUTINE GetM11 (MoveFlag) = ! Get a MACY11 record
!++
! FUNCTIONAL DESCRIPTION:
!
! Get a record from an open MACY11 file.
!
! FORMAL PARAMETERS:
!
! MOVEFLAG: True if we want the data, False if skipping record
!
! IMPLICIT PARAMETERS:
!
! RAB: A RAB as defined by RMS
!
! COMPLETION CODES:
!
! Standard RMS codes
!
! SIDE EFFECTS:
!
! NONE
!
!--
BEGIN
BIND Cbkd=Rst[Rst$z_Current_Bucket]: $Rms_Bucket_Descriptor;
LOCAL recordsize;
LOCAL bufptr: VECTOR[2];
LOCAL left;
IF .MoveFlag
THEN bufptr = UAPointer( CH$PTR(.Rab[Rab$a_Ubf],0,8) ) ! Use user's buffer
ELSE bufptr = 0; ! Use pointer to bit bucket
left=.Rst[Rst$g_Highest_Byte] ! counts bytes left in file
-(((.Cbkd[Bkt$h_Number]+1)*512*4)-.Rst[Rst$h_Byte_Count]);
SELECT .Fab[Fab$v_Rfm] OF
SET
[Fab$k_Fix]:
BEGIN
IF (.left LSS .Rab[Rab$h_Rsz]) THEN UserError(RMS$_EOF);
! EOF if not enough bytes for one full record.
recordsize = .Fab[Fab$h_Mrs]
END;
[Fab$k_Var]:
BEGIN
IF .left LSS 4 THEN UserError(RMS$_EOF);
! Don't be fooled by up to 3 filler bytes at end.
IF M11Gby() NEQ 1 THEN UserError( RMS$_UDF );
M11GBy(); ! Filler
recordsize = M11GBy()+(M11GBy()^8)-4 ! Record size including header
END;
TES;
DECR i FROM .Rab[Rab$h_Rsz]-1 TO 0
DO CH$WCHAR_A(M11GBy(),bufptr);
IF .Fab[Fab$v_Rfm] EQL Fab$k_Var
THEN (DECR i FROM 6 TO 0 DO M11GBy()); ! Eat checksum & filler
.recordsize ! Return size of record
END; !End of GETM11
GLOBAL ROUTINE FndM11 =
BEGIN
LOCAL sizeoflastrecrd;
!+
! If we are at EOF, then don't try finding a record.
!-
IF endoffile THEN usererror (er$eof);
!+
! If the last RMS operation issued was a $FIND, or if the
! last record fetched was too big for the user's buffer
! (i.e., "partial" record), then we must skip a record and
! position ourselves to the next one. In all other cases
! (i.e., the last JSYS was a $OPEN or $GET), we are
! already positioned at the correct place.
!
! This module also must insure that the current record's
! starting address is maintained correctly. This
! procedure varies depending upon the current file
! context. For instance, if two successive $FINDs are
! done, a record must be skipped and its length added to
! the starting address of the last record. If the last
! record access was a "partial" record, the length of that
! record must be added to its starting address, then the
! rest of the record must be skipped and the amount that
! was skipped also added into the current RFA address.
!
! For normal conditions (i.e., a $FIND is done after a
! successful $GET or $FIND), then the length of the last
! record (i.e., current record to the user) must be added
! to its starting byte number to produce the address of
! the next record, which then immediately becomes the
! current record.
!-
IF (.rst [rstlastoper] EQL c$find) OR ! If last RMS call was a $FIND
(partialflag NEQ 0) ! or last record was too big.
THEN
BEGIN ! To skip a record
IF partialflag NEQ 0
THEN ! We must update current RFA
BEGIN
sizeoflastrecrd = .rst [rstrsz]; ! Get last record's size
! Compute start of this record
rst [rstdatarfa] = .rst [rstdatarfa] + .sizeoflastrecrd;
lookat (' SIZEOFLAST: ', sizeoflastrecrd)
END;
rst [rstrsz] = getm11 (false); ! Skip a record
clrflag (rst [rstflags], flgpartial); ! Clear the partial flag
END;
!+
! We must now update the RFA to point to the current
! record's starting address.
!-
rst [rstdatarfa] = ! Compute start of next record
.rst [rstdatarfa] + .rst [rstrsz];
!+
! Clear the "update the pointer" flag.
!-
clrflag (rst [rstflags], flgupdptr);
!+
! Return RFA to user
!-
rab [rabrfa, 0] = .rst [rstdatarfa]; ![2] Return RFA to user
RETURN true
END; ! End of FNDM11
GLOBAL ROUTINE PutM11 : NOVALUE = ! Put a MACY11 record
!++
! FUNCTIONAL DESCRIPTION:
!
! Put a record to an open MACY11 file.
!
!
! IMPLICIT PARAMETERS:
!
! RAB: A RAB as defined by RMS
!
!--
BEGIN
LOCAL bufptr;
LOCAL cksm;
bufptr=UAPointer(CH$PTR(.Rab[Rab$a_Rbf],0,8)); ! Make byte pointer of it
SELECT .Fab[Fab$V_Rfm] OF
SET
[Fab$k_Fix]: Rab[Rab$h_Rsz]=.Fab[Fab$h_Mrs];
[Fab$k_Var]:
BEGIN ! Put out the header
LOCAL rsz;
rsz=.Rab[Rab$h_Rsz]+4; ! MACY11 record size includes hdr
M11PBy(1); ! sync
M11PBy(0); ! sync
M11PBy(.rsz AND %O'377'); ! Record length
M11PBy((.rsz^-8) AND %O'377'); !
cksm=.rsz+(.rsz^-8)+1; ! Checksum so far
END;
TES;
DECR i FROM .Rab[Rab$h_Rsz]-1 TO 0
DO BEGIN
LOCAL c;
M11PBy( c=CH$RCHAR_A(bufptr) );
cksm=.cksm+.c; ! count in checksum
END;
IF .Fab[Fab$v_Rfm] EQL Fab$k_Var
THEN
BEGIN
M11PBy( (-.cksm) AND %O'377' ); ! Put out negative checksum
DECR i FROM 5 TO 0
DO M11PBy(0); ! and 6 bytes of 0
END;
END; !End of PUTM11
ROUTINE M11GBy = ! Get MACY11 byte
!++
! FUNCTIONAL DESCRIPTION:
!
! Get byte to MACY11 file
!
! IMPLICIT INPUTS:
!
! RAB: A RAB as defined by RMS
!
! ROUTINE VALUE:
!
! The byte
!
!--
BEGIN
IF .Rst[Saved_Byte] EQL No_Byte
THEN
BEGIN
BIND Pagptr=Rst[Rst$g_Page_Pointer]; ! Byte pointer in bucket
BIND Cbkd=Rst[Rst$z_Current_Bucket]: $RMS_BUCKET_DESCRIPTOR;
IF .rst[Rst$h_Byte_Count] LEQ 0 ! bucket used up?
THEN
BEGIN
LOCAL rsz;
rsz=.rab[Rab$h_Rsz]; ! Save recordsize
Rab[Rab$g_Bkt]=.rab[Rab$g_Rfa]+1; ! Next page
Get_Bucket( Bucket=.Rab[Rab$g_Bkt], Desc=Cbkd );
Pagptr=%O'442200000000'+.CBkd[Bkt$a_Address]; ! Point to it
Rst[Rst$h_Byte_Count]=512*4; ! This many will fit on a page
Rab[Rab$h_Rsz]=.rsz; ! Restore recordsize
END;
Rst[Saved_Byte]=CH$RCHAR_A(Pagptr);
Rst[Rst$h_Byte_Count]=.rst[Rst$h_Byte_Count]-1;
RETURN (.Rst[Saved_Byte] AND %O'377')
END
ELSE
BEGIN
LOCAL v;
Rst[Rst$h_Byte_Count]=.Rst[Rst$h_Byte_Count]-1;
v=(.Rst[Saved_Byte] ^ -8) AND %O'377'; ! Other half
Rst[Saved_Byte]=No_Byte;
RETURN .v
END
END; !End of M11GBY
ROUTINE M11Pby (Char) : NOVALUE = ! Put MACY11 byte
!++
! FUNCTIONAL DESCRIPTION:
!
! Put byte to MACY11 file
!
! FORMAL PARAMETERS:
!
! CHAR: byte to put
!
! IMPLICIT INPUTS:
!
! RAB: Addr of RMS RAB
!
!--
BEGIN
BIND Pagptr=Rst[Rst$g_Page_Pointer]; ! Byte pointer in bucket
BIND Cbkd=Rst[Rst$z_Current_Bucket]: $Rms_Bucket_Descriptor;
IF .Rst[Rst$h_Byte_Count] LEQ 0 ! bucket used up?
THEN
BEGIN ! we need a new one
LOCAL rsz;
rsz=.Rab[Rab$h_Rsz];
Put_Bucket( Desc=Cbkd );
Rab[Rab$g_Bkt]=.Rab[Rab$g_Rfa]+1; ! Next page
Get_Bucket( Desc=Cbkd, Bucket = .Rab[Rab$g_Bkt] );
Pagptr=%O'442200000000'+.Cbkd[Bkt$a_Address]; ! Point to bucket
Rst[Rst$h_Byte_Count]=512*4; ! This many will fit on a page
Rab[Rab$h_Rsz]=.rsz; ! Restore recordsize
END;
IF .Rst[Saved_Byte] NEQ No_Byte
THEN
BEGIN
CH$WCHAR_A(.Rst[Saved_Byte]+(.Char^8),Pagptr);
Rst[Saved_Byte]=No_Byte;
END
ELSE
BEGIN
Rst[Saved_Byte]=.Char;
CH$WCHAR(.Char, .Pagptr) ! In case EOF comes immediately
END;
Rst[Rst$h_Byte_Count]=.Rst[Rst$h_Byte_Count]-1;
END; !End of M11PBY
GLOBAL ROUTINE CncM11 : NOVALUE =
!++
! FUNCTIONAL DESCRIPTION
!
! Special CONNECT-time setup for MACY11 files
!
! IMPLICIT PARAMETERS:
!
! RAB: A RAB as defined by RMS
!--
BEGIN
BIND Cbkd=Rst[Rst$z_Current_Bucket]: $Rms_Bucket_Descriptor;
BIND Pagptr=Rst[Rst$g_Page_Pointer]; ! Byte pointer in bucket
%IF %SWITCHES(TOPS20)
%THEN
BEGIN
LOCAL fdbbuf: VECTOR[$FBLEN];
! Set up byte count, and adjust if 36-bit bytes
GTFDB(.Fab[Fab$h_Jfn],$FBLEN^18,fdbbuf);
Rst[Rst$g_Highest_Byte]=.fdbbuf[$FBSIZ];
IF (.POINTR((fdbbuf[$FBBYV]),FB_BSZ)) EQL 36
THEN Rst[Rst$g_Highest_Byte]=.Rst[Rst$g_Highest_Byte]*4;
END;
%ELSE
Rst[Rst$g_Highest_Byte] = .Fst[Fst$g_Sof_Words] * 4;
%FI
Rst[Rst$h_Byte_Count]=0; ! No bytes available now
Rst[Saved_Byte]=No_Byte; ! No saved byte yet
Rab[Rab$g_Bkt]=1; ! First page
Get_Bucket( Desc=CBkd, Bucket=.Rab[Rab$g_Bkt] );
Pagptr=%O'442200000000'+.Cbkd[Bkt$a_Address]; ! Point to it
Rst[Rst$h_Byte_Count]=512*4; ! This many bytes will fit on a page
END; !CncM11
GLOBAL ROUTINE DscM11 : NOVALUE =
!++
! FUNCTIONAL DESCRIPTION
!
! Special $CLOSE for MACY11 files
!
! IMPLICIT PARAMETERS:
!
! FAB: A FAB as defined by RMS
!--
BEGIN
BIND Rst=.Fst[Fst$a_Flink]: $Rms_Rst; ! Record status table
BIND Cbkd=Rst[Rst$z_Current_Bucket]: $Rms_Bucket_Descriptor;
LOCAL size;
%IF %SWITCHES(TOPS20)
%THEN
IF .Fab[Fab$v_Put] ! If writing this file
THEN ! then fix up byte count
BEGIN ! and byte size
size=(.Cbkd[Bkt$h_Number]+1)*512*4 ! Buckets times bytes per bucket
-.Rst[Rst$h_Byte_Count]; ! Less unused bytes at end
size=(.size+3)/4; ! convert to words to satisfy NFT.
WBucket(); ! Write out current bucket
CHFDB(CF_NUD OR ($FBSIZ^18) OR .Fab[Fab$h_Jfn],-1,.size);
CHFDB(CF_NUD OR ($FBBYV^18) OR .Fab[Fab$h_Jfn],FB_BSZ,FLD(36,FB_BSZ));
! Fix the FDB up
Rst[Rst$h_Byte_Count]=0; ! Keep RMS from changing EOF
END;
%FI
END; !DscM11
END !End of module
ELUDOM