Google
 

Trailing-Edge - PDP-10 Archives - tops20-v7-ft-dist1-clock - 7-sources/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