Google
 

Trailing-Edge - PDP-10 Archives - BB-JF18A-BM - sources/rms/rmslib.r36
There are 28 other files named rmslib.r36 in the archive. Click here to see a list.
!   RMSLIB.R36
!<BLF/MACRO>
!<BLF/LOWERCASE_USER>
!<BLF/UPPERCASE_KEY>
! **		LIBRARY FILE REQUIRED BY RMS 		**
!
!
!
!	COPYRIGHT (C) DIGITAL EQUIPMENT CORPORATION 1979, 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.
!
!
! AUTHOR: S. BLOUNT
!

%IF NOT %DECLARED (%QUOTE MONWORD)
%THEN
LIBRARY 'bli:tendef';
%FI
!+
!
!    REVISION HISTORY:
!
!    EDIT#	NAME	DATE		COMMENTS
!    ====	====	====		=========
!    1	JK	27-JUL-76	ADD "CHECKEXACTCOUNT" MACRO TO CHECK FOR CORRECT ROUTINE ARG COUNT.
!    2	SB	30-SEP-76	ADD DBUG TO CHECKEXACTCOUNT
!    1	JK	20-AUG-76	ADD 'MAKERFA' MACRO.
!    2	SB	23-AUG-76	CHANGE 'MOVEDOWN' BUG
!    3	JK	23-AUG-76	ADD 'FLGRRVUPD' FOR DATA RECORD FLAGS.
!    4	SB	24-AUG-76	ADD SIZEOFANYRECORD MACRO, CHANGE SIZEOFDATARECORD
!
!    5	JK	30-AUG-76	FIX SIZEOF... MACROS.
!    6	SB	30-AUG-76	CHANGE THISAREA FIELD PLACEMENT
!
!    7	JK	30-AUG-76	ADD 'BHUNUSED' FOR UNUSED BKT HDR BITS.
!    8	JK	1-SEP-76	ADD 'FIRSTID' AND 'NULLID'.
!    9	JK	1-SEP-76	FIX 'MAKERFA'.
!    10	AS	4-SEP-76	ADD W2B SHIFT.
!    11	SB	22-SEP-76	ADD PATH DEFINITIONS
!    12	SB	24-SEP-76	ADD SOME SIDR DEFINITIONS
!    13	SB	30-SEP-76	MAKE MOVEDOWN USE PUSHJ, NOT CALL0
!    14	SB	30-SEP-76	ADD MININDEXRECS
!    15	SB	7-OCT-76	CHANGE SIZEOFDATARECORD TO NOT COMPUTE SIDR LENGTH
!    16	SB	20-OCT-76	ADD RFABKTLSH
!    17	SB	5-NOV-76	ADD LOWESTBKTNUM DEFINITIONS
!    18	SB	7-NOV-76	MAKE BUCKETS INTO PAGES...
!    19	SB	23-NOV-76	TAKE OUT ALL BUCKET DESC DEFINITIONS
!    20	SB	6-DEC-76	ADD NO-COMPRESS BIT IN RECORD HEADER
!    21	SB	16-DEC-76	CHANGE KDBDBSZ TO FSTBSZ
!    22	SB	23-DEC-76	ADD DEFBUCKETSIZE
!    23	SB	1-FEB-77	ADD NOHIKEYUPDFLAG
!    24	SB	13-APR-77	FIX SIZEOFDATARECORD
!
!
!    PRODUCT	MODULE	 SPR
!    EDIT	 EDIT	 QAR		DESCRIPTION
!    ======	======	=====		===========
!
!    13	27	XXXXX		NO SYMPTOM, BUT MACRO CLEAR HAS LAST EXPRESSION
!    MISSING THE FETCH OPERATOR ('.').
!
!
!    ***** BEGIN VERSION 2 DEVELOPMENT *****
!
!
!    PRODUCT	MODULE	 SPR
!    EDIT	 EDIT	 QAR		DESCRIPTION
!    ======	======	=====		===========
!
!    300	300	XXXXX		MAKE DBUG=1 WORK.
!
!    301	301	XXXXX		SUPPORT EXTENDED ADDRESSING.
!
!    302	302	XXXXX	JSM	REFORMAT EXTERNAL CALLS FOR BLISS VER 3
!
!    303	303	XXXXX	RL	GET RID OF CALLING MACROS
!
!    400	400	xxxxx		Clean up BLISS code (RL,22-Apr-83)
!
!    406       	-	xxxxx		Remove external definitions and
!					create RMSEXT.R36 (RL,12-May-83)
!
!    411                xxxxx           Implement new key datatypes
!
!    425	-	xxxxx		Fix CSTRINGLE_EA (RL,27-Sep-83)
!
!    426	-	xxxxx		Turn off tracing when not debugging
!					in TRACE and RMSENTRY macros
!					(RL,28-Sep-83)
!
!    442	-	xxxxx		Add ALCBKT function to UTLINT calls
!					(RL, 9-Dec-83)
!
!    455	-	xxxxx		Add DTP$K_xxx datatype literals.
!					(RL, 3-Feb-84)
!
! *** VERSION 3 DEVELOPMENT ***
!
!    501			        Fix definitions conflicting
!                                       with RMSSYS and TENDEF:
!                                       Remove BPT, PUSHJ, DEBUGERROR
!                                       (nothing uses)
!                                       Remove BUGOUT (in RMSSYS)
!                                       Remove all macros that gave
!                                       %INFORM messages as obsolete
!
!   610					Define Knmcharsiz

!+
!
!    ***********************************************************************
!    *			NUMERIC VARIABLES			           *
!    ***********************************************************************
!
!-


LITERAL
    allones = -1,				! Obvious
    plusinfinity = %O'377777777777';		! Positive infinity

%(
%IF NOT %DECLARED(false)                                          !a510
%THEN LITERAL false=0;                                            !a510
%FI                                                               !a510
                                                                  !a510
%IF NOT %DECLARED(true)                                           !a510
%THEN LITERAL true=-1;                                            !a510
%FI                                                               !a510
)%

!+
!
!    ***********************************************************************
!    *			USEFUL MACROS				           *
!    ***********************************************************************
!
!-

!
! Define bit numbering like the POINT pseudo-op does
!

MACRO
    bitn (n) =
	1^(35 - n) %;				! SHOULD BE DEFINED HERE***

MACRO
    comment =
    %,
    $xwd (left, right) =
	left^18 OR right %,			! XWD macro
    repeat =

	WHILE true DO

    %,						! INFINITE LOOP
    wrd =
	0, 36, 0 %,				! CONTENTS OF ENTIRE WORD
    rh =
	0, 18, 0 %,				! RIGHT HALF OF WORD
    lh =
	18, 18, 0 %,				! LEFT HALF OF WORD
    page =
	0, 9, 9, 0 %,				! PAGE NUMBER (BITS 18-26)
    pagemask =
	%O'777000' %,				! MASK FOR PAGE NUMBER
    ofset =
	0, 0, 9, 0 %,				! OFFSET INTO PAGE
    wholeword =
	0, 0, 36, 0 %,				! USED FOR POINTERS
    ptr7 =
	36, 7 %,				! LEFT HALF OF 7-BIT PINTER
    ptr6 =
	36, 6 %,				! SAME FOR SIXBIT
    ptr36 =
	36, 36 %,				! SAME FOR FULL-WORDS
    lastasciiptr =
	1, 7 %,					! LAST BYTE IN ASCII WORD
    addr (z) =
	(z) %,					! ADDRESS OF VARIABLE
    setflag (a, b) =
	a = .a OR b %,				! SET A BIT
    chkflag (a, b) =
	(.a AND b) %,
    clrflag (a, b) =
	a = .a AND ( NOT b) %;

!+
!    SOME VALUES FOR BYTE POINTERS
!-

LITERAL
    nullbp = %O'440000';			! A LEFT-JUSTIFIED BYTE PTR

MACRO
    $stradd (string$) =
	UPLIT (%ASCIZ %STRING(string$)) %;

! TEXT OUTPUTTING MACROS
!+
!    MACRO TO TYPE OUT A STRING USING A FORMAT STATEMENT
!-
!

MACRO
    txtout (fmt) =
	BEGIN

	EXTERNAL
	    %NAME (fmt);

	%IF %LENGTH NEQ 1			! Some other args?
	%THEN
	    tx$out (%REMAINING, %NAME (fmt))
	%ELSE
	    tx$out(%NAME (fmt))
	%FI

	END
    %;

!+
!    MACRO TO TYPE OUT A TEXT STRING
!-

MACRO
    type (text) =
	! TYPE OUT A MESSAGE ON THE TTY
	BEGIN
	txtout (mf$asz, UPLIT (%ASCIZ text));
	END
    %;

!+
!    MACRO TO OUTPUT DEBUGGING MESSAGES
!-

!+
!    MACROS FOR ERROR MESSAGES IN EXTREME SITUATIONS
!-

MACRO
    msg (text) =
	BEGIN					! THIS MACRO USED PRIMARILY IN UNIT-TESTS
	type (%STRING ('?', text));
	END
    %;

!+
!    MACRO TO PERFORM A BLOCK TRANSFER OF DATA
!-

MACRO
    movewords (fromloc, toloc, size) =
	BEGIN

	REGISTER
	    bltac,
	    xxxxac;

	xxxxac<lh> = fromloc;
	xxxxac<rh> = toloc;
	bltac = .xxxxac + size - 1;
	blt (xxxxac, 0, bltac);
	END
    %;

!+
!    MACRO TO CLEAR A BLOCK OF MEMORY
!-

MACRO
    clear (ptr, len) =
	! CLEAR A SERIES OF CORE LOCATIONS
	BEGIN

	REGISTER
	    temp1,
	    temp2;

	temp1 = ptr;				! BLOCK ADDRESS
	temp2 = .temp1 + len - 1;
	(.temp1)<wrd> = 0;

	IF len GTR 1				!BLT NECES?
	THEN
	    BEGIN				!YES, MULTI-WD
	    hrl (temp1, temp1);
	    aoj (temp1);
	    blt (temp1, 0, temp2);
	    END;

	END
    %;


!+
!
!    ***********************************************************************
!    *			MISCELLANEOUS VALUES THAT ALL MODULES USE	*
!    ***********************************************************************
!
!-
!+
!    SIZE OF A SINGLE PHYSICAL PAGE
!-

LITERAL
    pagesize = 512;

!+
!
!    ***********************************************************************
!    *			MACROS TO SIMPLIFY VARIOUS COMPUTATIONS      *
!    ***********************************************************************
!
!-
!+
!    MACRO TO COMPUTE THE TOTAL SIZE IN WORDS OF A DATA RECORD
!-

MACRO
    sizeinwords (recordsize, bytesize) =
	BEGIN

	LOCAL
	    bytes,
	    words;

	bytes = 36/bytesize;			!# OF BYTES PER WORD
	words = recordsize/.bytes;		! SIZE OF EACH RECORD IN WORDS

	IF (recordsize MOD .bytes) NEQ 0 THEN words = .words + 1;	! ACCOUNT FOR SLACK BYTES

	.words					! RETURN VALUE
	END
    %;

!+
!
!    ***********************************************************************
!    *			 MACROS FOR SHIFTING QUANTITIES		      *
!    ***********************************************************************
!
!-

LITERAL
    leftlsh = 18,				! SHIFT INTO LEFT-HALF OF WORD
    divideby2lsh = -1,				! DIVIDE VALUE BY 2
    p2w = 9,					! SHIFTING CONSTANT FOR PAGES/WORDS
    w2p = -9,					! WORDS TO PAGES
    s2p = -9;					! LH (SECTIONS) TO PAGES

!+
!
!    ***********************************************************************
!    *			ERROR PROCESSING MACROS			      *
!    ***********************************************************************
!
!-
!+
!    MACRO TO SET UP ADDRESS OF USER BLOCK FOR STATUS
!-

MACRO
    errorblock (a) =
	pb = .a %;				! SET UP BLOCK FOR ERROR STATUS

!+
!    MACRO TO DEFINE A USER ERROR AND EXIT TO USER
!-

MACRO
    procerr (CODE, action) =
	! MACRO TO DESC ERROR
	BEGIN
	usrsts = CODE;

	%IF dbug
	%THEN
	    begindebug (dberrors)		! SPECIAL DEBUGGING TRACE
!+
! Allow user to return the error code in a variable called "ERRORCODE"
!  if he doesn't want to return the immediate value. This allows compilation
!  to succeed with DBUG=1.
!-

	    %IF %IDENTICAL (CODE, .errorcode)
	    %THEN
		printvalue(%STRING ('?USER ERROR FOUND: '), errorcode)
	    %ELSE
		txtout(mf$uef, UPLIT (%ASCIZ'CODE'))
	    %FI

	    enddebug;
	%FI

	action
	END
    %;

MACRO
    usererror (CODE) =
	procerr (CODE, (usrerr ())) %;

MACRO
    returnstatus (CODE) =
	procerr (CODE, (RETURN false)) %;

!+
!    MACRO TO DECLARE AN INTERNAL ERROR CONDITION
!-

MACRO
    rmsbug (ercod) =
	! INTERNAL CONSISTENCY
						!   ERROR FOUND
	BEGIN
	crash (r$$name, ercod)
	END
    %;

!+
!
!    ***********************************************************************
!    *			DEBUGGING MACROS			      *
!    ***********************************************************************
!
!-
!+
!    MACRO TO CHECK THE VALUE OF A SUBROUTINE INPUT ARGUMENT
!-

MACRO
    checkinput (argnam, optr, argval) =

	%IF dbug
	%THEN
	    BEGIN

	    IF NOT (.argnam optr argval) THEN rmsbug (msginput)

	    END
	%FI

    %;

MACRO
    dbugout (case$) =

	%IF dbug
	%THEN
	    begindebug (case$)				!
	    type(%STRING (%REMAINING));			!
	    enddebug;
	%FI

    %;

!<BLF/NOMACRO>
!<BLF/NOFORMAT>
!<BLF/NOERROR>
	MACRO
	    begindebug (flagname) =
		BEGIN

		IF ((.bugflg AND flagname) NEQ 0)
		THEN
		    BEGIN
		    %

		, enddebug =
		END
		END
	    %;

!<BLF/MACRO>
!<BLF/FORMAT>
!<BLF/ERROR>
!+
!    MACRO TO TRACE THE ENTRY TO AN RMS-20 VERB PROCESSOR
!-

MACRO
    rmsentry (verbname) =

	BIND
	    r$$name = UPLIT (%ASCIZ %STRING(verbname));

	%IF dbug				!			!A426
	%THEN					!			!A426
	BEGIN
	begindebug (dbentry)			!
	txtout(mf$ent, r$$name);		!
	enddebug;
	END
	%FI					!			!A426
    %;

!+
!    MACRO TO PERFORM AN ENTRY TRACE OF A SPECIFIC ROUTINE
!-

MACRO
    TRACE (rname) =
	! TRACE RMS EXECUTION


	BIND
	    r$$name = UPLIT (%ASCIZ rname);	! SAVE ROUTINE NAME

	%IF dbug				!			!A426
	%THEN					!			!A426
	BEGIN
	begindebug (dbtrace)			!
	txtout(mf$enr, r$$name);		!
	enddebug;				!
	END					!
	%FI					!			!A426
    %;

!+
!    MACRO TO PRINT THE CONTENTS OF A VARIABLE <ALWAYS>
!-

MACRO
    printvalue (text, pr_field) =

	%IF dbug
	%THEN
	    BEGIN

	    EXTERNAL
		dextr1;

	    txtout (mf$con, UPLIT (%ASCIZ text));	!Message continues..
	    dextr1 = .pr_field;
	    dump (1, .dextr1)			!Type value and CRLF
	    END
	%FI

    %;

!+
!    MACRO TO PRINT VALUE OF A FIELD IF DEBUG IS ON AND DBLOCAL IS SET
!-

MACRO
    lookat (text, pr_field) =

	%IF dbug
	%THEN
	    begindebug (dblocal)		!
	    printvalue(text, pr_field);		!
	    enddebug
	%FI

    %;

!+
!    MACRO TO TRACE EXECUTION OF A SINGLE ROUTINE
!-

MACRO
    rtrace (text) =
	! USE THIS FOR ROUTINE TRACING
	dbugout (dbrtrace, text);
    %;

!+
!    MACRO FOR UN-IMPLEMENTED FUNCTIONS
!-

MACRO
    notdone (a) =
	BEGIN
	type (%STRING (a, ' IS NOT IMPLEMENTED YET'));
	END
    %;

!+
!    MACRO TO DECLARE A FILE CONSISTENCY PROBLEM
!-

MACRO
    fileproblem (errcode) =
	BEGIN
	usrsts = er$udf;
	usrstv = errcode
	END
    %;

!+
!    MACROS FOR INCREMENTING AND DECREMENTING VARIABLES
!-

MACRO
    currentjsys =
	(.ujsys<rh> AND %O'77') %;

!+
!
!    ***********************************************************************
!    *			DEBUGGING VERBOSITY FLAGS		      *
!    ***********************************************************************
!
!-
!+
!    THESE FLAG BITS DEFINE THE LEVEL OF THE DEBUGGING
!    VERBOSITY OUTPUT WHICH IS TYPED.  THEY EXIST IN
!    THE "BUGFLG" WORD.
!-
!+
!    *****NOTE THAT THESE BIT DEFINITIONS MUST CORRESPOND
!    TO THE SAME BITS DEFINED IN RMSSYM.MTB. IN FACT, THESE
!    BITS SHOULD BE ELIMINATED ALTOGETHER.
!-

LITERAL
    dbtrace = bitn (35),			! MODULE TRACE
    dberrors = bitn (34),			! USER ERRORS
    dbrtrace = bitn (33),			! ROUTINE TRACE
    dblocal = bitn (32),			! LOCAL VARIABLES
    dbblocks = bitn (31),			! DUMP OF VARIOUS BLOCKS
    dblock = bitn (30),				! PRINT TRACE OF RECORD LOCKS
    dbio = bitn (29),				! TRACE I/O ACTIVITY
    dbentry = bitn (28);			! TRACE ENTRY TO RMS-20

!+
!
!    ***********************************************************************
!    *			ASCII CHARACTER  CODES		      *
!    ***********************************************************************
!
!-

LITERAL
    chartab = %O'11',				! HORIZONTAL TAB
    charlf = %O'12',				! LINE FEED
    charvt = %O'13',				! VERTICAL TAB
    charff = %O'14',				! FORM FEED
    char0 = %O'60',				! "0"
    charcr = %O'15',				! CARRIAGE RETURN
    charcntz = %O'32';				! CONTROL-Z

!+
!
!    ***********************************************************************
!    *			REGISTER DEFINITIONS			      *
!    ***********************************************************************
!
!-
!+
!
!    ***********************************************************************
!    *		INTERNAL SUBROUTINE PARAMETER VALUES		    *
!    ***********************************************************************
!
!-
!+
!    THESE VALUES ARE BIT DEFINITIONS WHICH ARE PASSED TO
!    CERTAIN ROUTINES AS "ABORT FLAGS". EACH BIT REPRESENTS
!    A PARTICULAR OPERATION WHICH HAS BEEN PERFORMED AND MUST
!    BE UNDONE. CURRENTLY, OABORT AND CLEANUP ARE THE ONLY
!    ROUTINES WHICH USE THESE BITS
!-

LITERAL
    abrunlock = bitn (35),			! UNLOCK THE FILE
    abrclose = bitn (34),			! CLOSE THE FILE
    abrfpt = bitn (33),				! RELEASE THE FILE PROLOGUE TABLE
    abrfst = bitn (32),				! RELEASE THE FILE STATUS TABLE
    abrplogpage = bitn (31),			! RELEASE THE FREE PAGE
    abradb = bitn (30),				! RELEASE THE ADB
    abrulindex = bitn (29),			! UNLOCK THE CURRENT INDEX
    abrbucket = bitn (28);			! FLUSH THE CURRENT BUCKET

!+
!
!    ***********************************************************************
!    *			END OF MACROS.REQ			      *
!    ***********************************************************************
!
!-
!+
!
!    ********************************************************
!    *							*
!    *		START OF LIMITS.REQ			*
!    *							*
!    *		CONTENTS:				*
!    *							*
!    *	1. USER PARAMETER LIMIT DEFINITIONS		*
!    *							*
!    *********************************************************
!
!    AUTHOR: S. BLOUNT
!
!
!-
!+
!
!    ****************************************************************
!    *			KEY DESCRIPTION LIMITS			*
!    *****************************************************************
!
!-
!+
!    USER KEY-DEFINIITION LIMITS
!-

LITERAL
    maxkeys = 255,				! MAX # OF KEYS FOR THE FILE
    maxkeysegs = 8,				! MAX # OF KEY SEGMENTS
    maxkeysize = 255,				! SIZE OF KEY IN BYTES
    maxkszw = 64;				! SIZE OF KEY (IN WORDS)

						! WARNING: DUPL DEF IN RMSGLB
!+
!
!    ****************************************************************
!    *			AREA DEFINITION LIMITS			*
!    *****************************************************************
!
!-

LITERAL
    maxareas = 32;				! MAX # OF AREAS FOR THE FILE

!+
!
!    ****************************************************************
!    *			BUCKET PARAMETER LIMITS			*
!    *****************************************************************
!
!-

LITERAL
    maxfillpercent = 50,			! MAX FILE PERCENTAGE
    maxbkz = 7;					! MAX BUCKET SIZE (3 BIT FLD IN BFD)

LITERAL
    maxlevels = 15;				! MAX # OF INDEX LEVELS

						!MORE THAN BIG ENOUGH, EVEN WITH
						! HALF FULL BKTS AND 10 WD KEYS
						! ROOM FOR OVER 10**20 RECS
						!WARNING: DUPL DEF IN RMSGLB
!+
!
!    ****************************************************************
!    *			MISCELLANEOUS LIMITS				*
!    *****************************************************************
!
!-

LITERAL
    minuserbuff = %O'20',			! MINIMUM BUFFER ADDRESS
    minaddress = %O'20';			! GENERAL ADDRESS VALUE

!+
!
!    ****************************************************************
!    *			END OF LIMITS.REQ			*
!    *****************************************************************
!
!-
!+
!    ***************************************************************
!    *								*
!    *			START OF SWITCH.REQ			*
!    *								*
!    *		THIS FILE CONTAINS ALL COMPILATION		*
!    *		SWITCH VALUES WHICH MAY BE ALTERED		*
!    *		BEFORE RMS-20 IS INITIALLY BUILT.		*
!    *		THIS FILE IS USED BY ALL SOURCE MOD-		*
!    *		ULES WITHIN RMS-20.				*
!    *								*
!    ***************************************************************
!-
!+
!    DATA DECLARATION MACROS TO SELECT GLOBAL VARIABLES
!-

COMPILETIME
    indx = 1,
    dbug = %SWITCHES(DEBUG);

!+
!    ***************************************************************
!    *			END OF SWITCH.REQ			*
!    ***************************************************************
!-
!+
!
!    ********************************************************
!    *							*
!    *		START OF BUCKET.REQ			*
!    *							*
!    *		CONTENTS:				*
!    *							*
!    *	1. BUCKET FORMAT DEFINITIONS FOR INDEXED FILES  *
!    *	2. RECORD FORMAT DEFINITIONS FOR INDEXED FILES  *
!    *	3. MISCELLANEOUS MACROS FOR USE WITH RECORDS	*
!    *							*
!    *********************************************************
!
!    AUTHOR: S. BLOUNT
!
!
!-
!+
!
!    *****************************************************************
!    *		STRUCTURE OF BUCKET FOR INDEXED FILES		*
!    *****************************************************************
!
!-
!+
!
!    FORMAT OF BUCKET (INDEXED FILES ONLY)
!    =====================================
!
!    !=====================================!
!    !FLAGS!LEVEL! TYPE !    NEXT-BYTE     !
!    !-------------------------------------!
!    !<UNUSED> !  AREA  !     NEXTBKT      !
!    !-------------------------------------!
!    !      LASTID      !      NEXTID      !
!    !-------------------------------------!
!    !                                     !
!    !           RECORD STORAGE            !
!    !                AREA                 !
!    !                                     !
!    !-------------------------------------!
!    !             RRV STORAGE             !
!    !                AREA                 !
!    !-------------------------------------!
!    !                                     !
!    !             FREE SPACE              !
!    !                                     !
!    !=====================================!
!
!-
!+
!    DEFINITIONS RELATING TO THE SIZE OF A BLOCK
!-

LITERAL
    lengthofblock = pagesize/4,			! WORDS IN A BLOCK
    b2w = p2w,					! BUCKETS TO WORDS SHIFT
    w2b = w2p,					! WORDS TO BUCKETS
    b2p = 0,					! SHIFT FOR CONVERTING BLOCKS TO PAGES
    p2b = 0,					! SHIFT FOR CONVERTING PAGES TO BLOCKS
    bktfldsize = 18,				! # OF BITS TO HOLD A BKT #
    blocksperpage = 4;				! NO. BLOCKS IN A PAGE

!+
!    SYMBOLS RELATING TO THE SIZE OF A FILE BUCKET
!-

LITERAL
    lowestbktnum = 1,				! NO BUCKET CAN BE ON PAGE 0
    defbucketsize = 1;				! DEFAULT VALUE OF BKS FIELD

!+
!    STRUCTURE OF FIXED-LENGTH HEADER OF BUCKET
!-

LITERAL
    bhhdrsize = 3;				! SIZE OF HEADER

MACRO
    bhflags =
	0, 27, 9, 0 %,				! BUCKET FLAGS
    bhlevel =
	0, 21, 6, 0 %,				! LEVEL OF THIS BUCKET
    bhbtype =
	0, 18, 3, 0 %,				! BUCKET TYPE
    bhnextbyte =
	0, rh %,				! NEXT AVAIL WORD
    bhunused =
	1, 26, 10, 0 %,				! (UNUSED)
    bhthisarea =
	1, 18, 8, 0 %,				! THIS AREA
    bhnextbkt =
	1, rh %,				! PTR TO NEXT BUCKET
    bhlastid =
	2, lh %,				! LAST ID TO USE
    bhnextid =
	2, rh %;				! NEXT ID TO USE

!+
!    FLAGS DEFINED IN BUCKET HEADER
!-

LITERAL
    bhflgroot = bitn (35),			! THIS IS THE ROOT
    bhflgend = bitn (34);			! LAST BUCKET IN CHAIN

!+
!    BUCKET TYPES
!-

LITERAL
    btypeindex = 0,				! INDEX BUCKET
    btypedata = 1;				! DATA BUCKET

!+
!    VALUES USED FOR LEVELS OF THE INDEX (IF THESE CHANGE,
!    WE'VE GOT PROBLEMS
!-

LITERAL
    seqsetlevel = 1,				! LEVEL OF SEQUENCE SET
    datalevel = 0;				! LEVEL OF DATA

!+
!    VALUES WHICH DETERMINE IF A PARITCULAR INDEX OR DATA
!    BUCKET IS WRITTEN TO DISK WHEN IT IS RELEASED TO THE
!    BUCKET MANAGER. THESE VALUES ARE USED TO SPEED UP
!    PERFORMANCE IN THOSE CASES WHERE A COMPLETE DISK WRITE
!    MIGHT NOT BE ABSOLUTELY NECESSARY.
!-

LITERAL
    nohikeyupdflag = 0; ! false;		! DONT UPDATE THE INDEX !m510

						! BUCKET WHEN A DATA BUCKET
						! IS BEING REMOVED FROM THE INDEX.
						! THIS WILL NOT CAUSE ANY HARM,
						! BECAUSE THE INDEX STRUCTURE
						! IS STILL INTACT (SEE INSRTIREC)
!+
!
!    ****************************************************************
!    *			RECORD FILE ADDRESS (RFA) STRUCTURE	*
!    *****************************************************************
!
!-
!+
!    *******	NOTE	  *********
!-
!+
!    IN THE FOLLOWING RFA STRUCTURE MACROS, THE RECORD ID
!    IS IN THE LEFT HALF OF THE RFA WORD. HOWEVER, THE
!    HIGHEST ID WHICH IS EVER ALLOCATED IS #37777; THUS
!    BIT 0 IS NEVER USED. THIS BIT IS RESERVED IN SIDR
!    RECORDS FOR FUTURE USE. THE ID MACRO
!    BELOW COULD BE CHANGED TO CONSIST OF ONLY 17 BITS, BUT
!    THAT WOULD SLOW DOWN THE ACCESS TO RFA VALUES THRUOUT
!    THE SYSTEM.
!
!    FORMAT OF AN INDEXED FILE RFA
!    =============================
!
!    !=====================================!
!    !*!   RECORD ID    !  BUCKET NUMBER   !
!    !=====================================!
!
!
!-

MACRO
    rfabucket =
	0, rh %,				! BUCKET NUMBER
    rfaid =
	0, lh %;				! BUCKET ID

!+
!    SHIFTING VALUES FOR FIELDS IN AN RFA
!-

LITERAL
    id2rfalsh = 18,				! SHIFT ID TO RFA
    rfa2idlsh = -18;				! SHIFT RFA TO ID

!+
!    MASK VALUES
!-

LITERAL
    bucketmask = %O'777777';			! RIGHT HALF MASK

!+
!    MACRO TO BUILD AN RFA FROM BUCKET NO. AND ID
!-

MACRO
    makerfa (bktno, id) =
	id^id2rfalsh + bktno %;

!+
!    MACROS TO EXTRACT EACH FIELD FROM AN RFA
!-

MACRO
    idofrfa (rfavalue) =
	(rfavalue^rfa2idlsh) %,
    bucketofrfa (rfavalue) =
	(rfavalue AND bucketmask) %;

!+
!
!    ****************************************************************
!    *			RECORD FORMAT STRUCTURE			*
!    *****************************************************************
!
!-
!+
!
!    ****************************************************************
!    *			INDEX RECORD FORMAT			*
!    *****************************************************************
!
!-
!+
!    FORMAT OF INDEX RECORD:
!    ======================
!
!    !=====================================!
!    !      FLAGS       !  BUCKET POINTER  !
!    !-------------------------------------!
!    !                                     !
!    !             KEY STRING              !
!    !                                     !
!    !=====================================!
!
!
!-
!+
!    SIZE OF INDEX RECORD HEADER
!-

LITERAL
    irhdrsize = 1;				! 1 WORD FOR HEADER

!+
!    INDEX RECORD HEADER FORMAT
!-

MACRO
    irflags =
	0, lh %,				! FLAGS
    irbucket =
	0, 0, bktfldsize, 0 %;			! BUCKET NUMBER

!+
!    DEFAULT VALUE FOR FLAGS IN INDEX RECORD
!    ***SEE FLAG DEFINITIONS UNDER DATA RECORD***
!-

LITERAL
    defirflags = 0;

!+
!
!    ****************************************************************
!    *			DATA RECORD STRUCTURE			*
!    *****************************************************************
!
!-
!+
!
!    FORMAT OF GENERALIZED INDEXED DATA RECORD
!    =========================================
!
!
!    !=====================================!
!    !      FLAGS       !    RECORD ID     !
!    !-------------------------------------!
!    !           RECORD POINTER            !
!    !-------------------------------------!
!    !     <UNUSED>     !   RECORD SIZE    !
!    !-------------------------------------!
!    !                                     !
!    !             DATA RECORD             !
!    !                                     !
!    !=====================================!
!
!
!
!-
!+
!    SIZE OF DATA RECORD HEADER
!-
!+
!    NOTE THAT THE RECORD HEADER ON A USER DATA RECORD CAN
!    HAVE DIFFERENT LENGTHS, DEPENDING UPON WHETHER IT IS
!    A FIXED-LENGTH RECORD FILE OR A VARIABLE-LENGTH
!    RECORD FILE
!-

LITERAL
    fixhdrsize = 2,				! FIXED-FORMAT RECORDS
    varhdrsize = 3;				! VARIABLE-FORMAT RECORDS

!+
!    DATA RECORD FORMAT DEFINITIONS
!-

MACRO
    drflags =
	0, lh %,				! FLAGS
    drrecordid =
	0, rh %,				! ID OF THIS RECORD
    drrrvaddress =
	1, wrd %,				! POINTER TO RRV
!+
    !    DEFINITION OF RRV-ADDRESS FIELDS
    !-

    drrrvbucket =
	1, rh %,				! RRV BUCKET NUMBER
    drreserved =
	2, lh %,				! <UNUSED>
    drrecsize =
	2, rh %;				! RECORD SIZE

!+
!    OFFSETS INTO THE DATA RECORD WHERE THE RECORD SIZE IS STORED
!-

LITERAL
    varrszoffset = 2;				! VARIABLE RECORDS

!+
!    FLAG BITS DEFINED IN USER DATA/INDEX RECORD
!-

LITERAL
    defdrflags = 0;				! DEFAULT FLAGS

LITERAL
    flgdelete = bitn (35),			! THIS RECORD IS DELETED
    flgrrv = bitn (34),				! THIS IS AN RRV
    flghikey = bitn (33),			! THIS IS THE HIGHEST KEY POSSIBLE(INDEX ONLY)
    flgrrvupd = bitn (32),		! RRV RECORDS FOR THIS RECORD HAVE BEEN UPDATED (IN-CORE FLAG ONLY)
    flgnocompress = bitn (31);			! DON'T COMPRESS THIS RECORD

LITERAL
    defrrvflags = flgrrv;			! DEFAULT FLAGS FOR RRV RECORD

!+
!    MACRO TO ACCESS THESE FLAGS
!-

MACRO
    rrvflag (xrecptr) =
	(.xrecptr [drflags] AND flgrrv) %,
    deleteflag (xrecptr) =
	(.xrecptr [drflags] AND flgdelete) %;

!+
!
!    ********************************************************************
!    *			SECONDARY INDEX DATA RECORD STRUCTURE		*
!    *********************************************************************
!
!-
!+
!    FORMAT OF A SECONDARY INDEX DATA RECORD:
!    ========================================
!
!    !=====================================!
!    !      FLAGS       !    RECORD ID     !
!    !-------------------------------------!
!    !     <UNUSED>     !   RECORD SIZE    !
!    !-------------------------------------!
!    !                                     !
!    !              KEY VALUE              !
!    !                                     !
!    !-------------------------------------!
!    !               RFA #1                !
!    !-------------------------------------!
!    !                  .                  !
!    !                  .                  !
!    !                  .                  !
!    !-------------------------------------!
!    !               RFA #N                !
!    !=====================================!
!
!
!-
!+
!    SIZE VALUES FOR THE HEADER OF SECONDARY DATA RECORDS
!-

LITERAL
    sidrhdrsize = 2,				! ONLY 2 WORDS
    sidrbytesize = 36;				! BYTE SIZE FOR SIDR RECORDS

!+
!    SIDR FORMAT DEFINITIONS
!-

MACRO
    sidrrecsize =
	1, rh %,				! RECORD SIZE FIELD
    sidrdupcount =
	1, lh %;				! DUP COUNT (FUTURE)

!+
!    SIDR RECORD FLAG VALUES (NOT FLAGS IN RFA)
!-

LITERAL
    defsidrflags = 0;				! DEFAULT VALUES

!+
!    FLAG BIT DEFINITIONS FOR EACH RFA IN A SIDR ARRAY
!-

LITERAL
    nullrfa = 0,				! AN EMPTY RECORD POINTER
    allrfaflags = bitn (0);			! ONE BIT IS RESERVED

!+
!    OFFSET INTO THE SECONDARY RECORD WHERE THE RECORD SIZE IS KEPT
!-

LITERAL
    sidrrszoffset = 1;				! 2ND WORD OF HEADER

!+
!    MACROS USED TO MANIPULATE SIDR RFA'S TO DETERMINE IF
!    THE RFA IS DELETED.
!-

MACRO
    setdeletedrfa (arrayptr) =
	(arrayptr [wholeword] = nullrfa) %,
    deletedrfa (arrayptr) =
	(.arrayptr [wholeword] EQL nullrfa) %;

!+
!
!    ****************************************************************
!    *			RRV RECORD STRUCTURE			*
!    *****************************************************************
!
!-
!+
!    FORMAT OF A RRV RECORD:
!    ======================
!
!    !=====================================!
!    !      FLAGS       !    RECORD ID     !
!    !-------------------------------------!
!    !       ADDRESS OF RECORD (RFA)       !
!    !=====================================!
!
!
!-
!+
!    THE STRUCTURE OF AN RRV RECORD IS IDENTICAL TO THE
!    DEFINITION OF THE DATA RECORD FORMAT FOR ALL FIELDS
!    OF THE RRV RECORD
!-

LITERAL
    rrvrecsize = 2;				! SIZE OF AN RRV RECORD

!+
!
!    *****************************************************************
!    *		MACRO TO MOVE A PORTION OF A BUCKET DOWN		*
!    *****************************************************************
!
!-
!+
!    THIS MACRO IS USED WHEN A RECORD IS TO BE INSERTED
!    INTO A INDEX OR DATA BUCKET. IT IS A COMPLEX MACRO
!    SO AS TO MAXIMIZE THE EFFICIENCY OF THE OPERATION.
!    THIS OPERATION COULD ALSO BE DONE BE A "MOVE,MOVEM"
!    LOOP BUT IT WOULD NOT BE AS FAST AS THIS ALGORITHM.
!-
!+
!    THE MACRO WORKS AS FOLLOWS:
!
!    LET:
!    A	=	START OF CHUNK TO MOVE
!    B	=	START OF PLACE TO MOVE CHUNK
!    C	=	LAST WORD OF CHUNK TO MOVE
!    D	=	LAST WORD OF PLACE WHERE CHUNK WILL BE
!
!    THEN, WE SET THE AC TO BE:
!    AC/	XWD (C-A-1)+400000, C
!
!    AND DO THE FOLLOWING LOOP:
!
!    LOOP1:	POP	AC, D-C(AC)
!    LOOP2:	JUMPL	AC,.-1
!    LOOP3:	POPJ	P,
!
!
!    C-A-1 BECAUSE LOOPS TERMINATES WHEN LEFT HALF = 377777.
!    THIS EFFECTIVELY POPS THE DATA FROM ONE PLACE IN CORE
!    TO THE OTHER.
!
!-

MACRO
    movedown (xstart, xend, xamtdown) =
	BEGIN

	EXTERNAL
	    loop1,
	    loop2,
	    loop3;

	REGISTER
	    tempac = 1;

	loop1 = (%O'262'^27) OR (1^23) OR (1^18) OR (xamtdown);
	loop2 = (%O'321'^27) OR (1^23) OR loop1;
	loop3 = (%O'263'^27) OR (%O'17'^23);
	tempac = ((xend - xstart)^leftlsh) OR (xend);
	tempac = (.tempac OR (1^35));
	BEGIN

	BIND ROUTINE
	    revblt = loop1 : NOVALUE;

	revblt ();
	END;
	END
    %;

!+
!
!    *********************************************************
!    *							*
!    *	MISCELLANEOUS VALUES ASSOCIATED WITH BUCKETS	*
!    *							*
!    *********************************************************
!
!-

LITERAL
    highestid = %O'377777',			! HIGHEST LEGAL RECORD ID ( 17 BITS )
    highestbucketno = %O'777777',		! HIGHEST LEGAL BUCKET NO ( 18 BITS )
!
!	**note: The 'no' to HIGHESTBUCKETNO was added for BLISS 36.
!		The source module was using HIGHESTBUCKETNO even though
!		only HIGHESTBUCKET was declared. BLISS-10 did'nt care
!		but BLISS-36 looks at all 15 characters.
!
    firstid = 1,				! FIRST VALID BUCKET ID
    nullid = 0;					! NON-EXISTENT BKT ID

						! (USED TO INDICATE "ID NOT GIVEN")
!+
!
!    ********************************************************************
!    *			MISCELLANEOUS MACROS				*
!    *********************************************************************
!
!-
!+
!    MACRO TO DETERMINE THE SIZE OF A DATA RECORD
!    NOTE THAT THIS MACRO WORKS ONLY ON DATA RECORDS...NOT RRV'S
!-

MACRO
    sizeofdatarecrd (recptr) =
	BEGIN

	REGISTER
	    ac,
	    temp;

	IF .kdb [kdbref] NEQ refprimary
	THEN
	    ac = .recptr [sidrrecsize]
	ELSE
	    BEGIN

	    IF fixedlength THEN temp = .fst [fstmrs] ELSE temp = .recptr [drrecsize];

	    ac = sizeinwords (.temp, .fst [fstbsz])
	    END;				! OF ELSE THIS IS A UDR

	ac = .ac + .kdb [kdbhsz]		! ADD HEADER SIZE
	END
    %;						! OF SIZEOFDATARECRD

!+
!    MACRO TO FIND LENGTH OF JUST A USER DATA RECORD
!-

MACRO
    sizeofudr (recptr) =
	BEGIN

	REGISTER
	    temp;

	IF fixedlength THEN temp = .fst [fstmrs] ELSE temp = .recptr [drrecsize];

	sizeinwords (.temp, .fst [fstbsz]) + .kdb [kdbhsz]
	END
    %;						! OF SIZEOFUDR

!+
!    MACRO TO GET THE SIZE OF A "RECORD", EITHER A DATA
!    RECORD OR AN RRV RECORD
!-

MACRO
    sizeofanyrecord (recptr) =
	BEGIN

	IF rrvflag (recptr) NEQ 0 THEN rrvrecsize ELSE sizeofdatarecrd (recptr)

	END
    %;

!+
!    MACRO TO DE-ALLOCATE A FILE BUCKET.
!-
!+
!    **NOTE THAT THIS MACRO IS CURRENTLY NULL. THAT'S
!    BECAUSE SECONDARY BUCKET ALLOCATION (RE-USE OF
!    BUCKETS THAT ARE NO LONGER NEEDED) IS NOT CURRENTLY
!    SUPPORTED IN RMS-20. IN OTHER WORDS, UNTIL THIS MACRO IS IMPLEMENTED,
!    THERE WILL BE SOME WASTED SPACE IN THIS SITUATION
!-

MACRO
    deallocbucket (xbd, xsize) =
    %;

!+
!
!    ****************************************************************
!    *			STRUCTURES FOR "PATH" ARRAY		*
!    *****************************************************************
!
!-
!+
!    THESE TWO FIELDS ARE IN THE "PATH" ARRAY AND ARE
!    USED BY THE FNDREC AND IDXUPDATE TO LOCATE THE
!    INDEX BUCKET PATH USED TO PROCESS THE INDEX.
!-

MACRO
    pathbkt =
	0, bktfldsize, 0 %,			! BUCKET PROCESSED GOING DOWN INDEX
    pathoffset =
	bktfldsize, 18, 0 %;			! OFFSET INTO BUCKET OF

						! INDEX RECORD USED IN SEARCH
!+
!
!    ****************************************************************
!    *			END OF BUCKET.REQ			*
!    *****************************************************************
!
!-
!+
!
!    ******************************************************************
!    *			START OF BUFFER.REQ			   *
!    *								   *
!    *			CONTENTS:				   *
!    *								   *
!    *		1. ALL BUFFER MANAGEMENT DATA STRUCTURES    	   *
!    *								   *
!    *******************************************************************
!
!
!
!    THIS FILE CONTAINS ALL MACROS AND DEFINITIONS WHICH
!    RELATE TO THE BUFFER MANAGEMENT WITHIN RMS-20. THIS
!    INCLUDES THE FOLLOWING STRUCTURES:
!
!    1.	BUFFER DESCRIPTORS
!    2.	BUCKET DESCRIPTORS
!
!    THE BUFFER DESCRIPTORS ARE MAINTAINED WITHIN THE RST
!    FOR EACH RECORD STREAM. THESE DESCRIPTORS ARE NEVER
!    MOVED AROUNT NOR USED AS ARGUMENTS TO ANY ROUTINE.
!
!    THE BUCKET DESCRIPTORS ARE MULTI-WORD STRUCTURES WHICH
!    ARE PASSED AROUND BY MANY ROUTINES AND USED AS ARGUMENTS
!    FOR ROUTINES WHICH PROCESS INDEXED FILES. NOTE THAT
!    EXCEPT FOR THE "CURRENT BUCKET DESCRIPTOR" FIELD IN THE
!    RST, BUCKET DESCRIPTORS ARE NEVER PERMANENT...THEY
!    ARE CREATED, USED, AND LATER RELEASED. CONTRAST THIS
!    WITH THE BUFFER DESCRIPTORS WHICH ARE CREATED ONLY AT
!    $CONNECT-TIME, ARE NEVER MOVED, AND ARE RELEASED ONLY
!    WHEN THE RECORD STREAM IS DISCONNECTED.
!
!    THIS FILE CONTAINS NO INFORMATION OR DEFINITIONS CONCERNING
!    THE ACTUAL STRUCTURE OF EITHER A BUCKET OR THE RECORDS WITHIN
!    A BUCKET.
!
!-
!+
!
!    *****************************************************************
!    *		STRUCTURE OF BUFFER DESCRIPTORS			*
!    *****************************************************************
!
!-
!+
!    MACRO TO GET ADDRESS OF FIRST BUFFER DESCRIPTOR
!-

MACRO
    bfdoffset =
	addr (rst [rstbfd]) %;

!+
!    MACROS FOR ACCESSING FIELDS IN BUFFER DESCRIPTORS
!-

MACRO
    bfdbpage =
	0, 27, 9, 0 %,				! Page no. of buffer in core
    bfdusecount =
	0, 24, 3, 0 %,				! No. of users of this buffer
    bfdupdflag =
	0, 23, 1, 0 %,				! If on, data in buffer
    						! needs to be output
    bfdbktsiz =
	0, 20, 3, 0 %,				! # Of pages in bkt curr in buf
    						! 0 indics buf empty
    bfdfpage =
	0, 0, 18, 0 %;				! File page no. in first

						! page of buffer

MACRO
    bfdupd (bfd) =
	.bfd [bfdupdflag] NEQ 0 %;

MACRO
    setbfdupd (bfd) =
	BEGIN

	LOCAL
	    temp : REF BLOCK;

	temp = .bfd;
	temp [bfdupdflag] = 1
	END
    %;

MACRO
    clearbfdupd (bfd) =
	BEGIN

	LOCAL
	    temp : REF BLOCK;

	temp = .bfd;
	temp [bfdupdflag] = 0
	END
    %;

!+
!
!    *****************************************************************
!    *		STRUCTURE OF BUCKET DESCRIPTORS			*
!    *****************************************************************
!
!-
!+
!
!    THE FORMAT OF A BUCKET DESCRIPTOR IS AS FOLLOWS:
!
!    !=====================================!
!    !      BFDADR      !      BKTADR      !
!    !-------------------------------------!
!    !<*>!BKTSIZE!FLAGS !      BKTNO       !
!    !=====================================!
!
!
!-
!+
!    MACROS FOR ACCESSING FIELDS IN BUCKET DESCRIPTORS
!-

MACRO
    bkdbfdadr =
	0, lh %,				! Adr of buffer descriptor
    bkdbktadr =
	0, rh %,				! Adr of bucket in core
! ***NOTE UNUSED 4 BITS IN LEFT OF WORD 1***
    bkdbktsize =
	1, 24, 8, 0 %,				! Bucket size in blocks
    bkdflags =
	1, 18, 6, 0 %,				! Flags
    bkdbktno =
	1, rh %;				! Bucket no.

!+
!    SIZE OF A BUCKET DESCRIPTOR
!-

LITERAL
    bdsize = 2;

!+
!    MACRO TO DETERMINE IF A BUCKET DESCRIPTOR IS NULL
!-

MACRO
    nullbd (bd) =
	(.bd [bkdbktadr] EQL 0) %;

!+
!    MACRO TO SET A BUCKET DESCRIPTOR TO BE NULL
!-

MACRO
    setnullbd (bd) =
	(bd [bkdbktadr] = 0) %;

!+
!    MACRO TO INDIC THAT BKT MUST BE UPDATED
!-

MACRO
    setupd (bd) =
	setbfdupd (bd [bkdbfdadr]) %;

!+
!    BUCKET DESCRIPTOR FLAGS
!-

LITERAL
    bkdflglocked = bitn (35);			! BUCKET IS LOCKED

!+
!    VALUES USED FOR THE BUCKET SIZE OF NON-INDEXED FILES
!    **NOTE THAT FOR INDEXED FILES, THE BUCKET SIZE VALUE IS
!    A FILE-DEFINITION PARAMETER WHICH CAN POTENTIALLY VARY FOR
!    EACH FILE BUCKET. FOR NON-INDEXED FILES, THE BUCKET SIZE IS
!    ALWAYS IN TERMS OF PAGES.
!-

LITERAL
    asciibktsize = 1,				! USE PAGES
    seqbktsize = 1,				! SAME
    relbktsize = 1;				! SAME

!+
!    MACROS FOR ACCESSING BUCKET DESCRIPTOR FLAGS
!-

MACRO
    bktlocked (bkd) =
	(.bkd [bkdflags] AND bkdflglocked) NEQ 0 %;

MACRO
    setbktlocked (bkd) =
	setflag (bkd [bkdflags], bkdflglocked) %;

MACRO
    setbktunlocked (bkd) =
	bkd [bkdflags] = (.bkd [bkdflags] AND NOT (bkdflglocked)) %;

!+
!    MACRO TO MOVE A BUCKET DESCRIPTOR
!-

MACRO
    movebktdesc (xfrom, xto) =
	BEGIN
	xto [0, wrd] = .xfrom [0, wrd];
	xto [1, wrd] = .xfrom [1, wrd];
	END
    %;

!+
!    MACRO TO RETURN FILE PAGE OF A BUCKET
!-

MACRO
    filepage (bkd) =
	(.bkd [bkdbktno]) %;

!+
!    MACRO TO CAUSE A BUCKET TO BE UPDATED ON DISK
!-

MACRO
    updatebucket (bkd) =
	BEGIN

	IF ( NOT deferredwrite)
	THEN
	    BEGIN

	    LOCAL
		mempageglobal;

	    %IF dbug
	    %THEN
		lookat ('**	BKT WRITTEN TO DISK: ', bkd [bkdbktno]);
	    %FI

	    mempageglobal = (.bkd [bkdbktadr] OR .rmssec)^w2p;
	    pagout (.fst [fstjfn], 		! JFN
		filepage (bkd), 		! PAGE
		.mempageglobal, 		! MEM
		.bkd [bkdbktsize]);		! COUNT
	    clearbfdupd (bkd [bkdbfdadr])	!INSURE FLAG OFF
	    END
	ELSE
	    setbfdupd (bkd [bkdbfdadr])		!DONT FORGET WHEN DEFER
	END

    %;

!+
!
!    ***********************************************************************
!    *			END OF BUFFER.REQ			      *
!    ***********************************************************************
!
!-

!+
!
!    ***********************************************************************
!    *			instruc.req				           *
!    *									   *
!    *		1. machops and other machine-level symbols		   *
!    ***********************************************************************
!
!-

macro
    z [] =
	machop (%o'0', %remaining) %,
    sub [] =
	machop (%o'274', %remaining) %,
    skipe [] =
	machop (%o'332', %remaining) %,
    tlc [] =
	machop (%o'641', %remaining) %,
    lsh [] =
	machop (%o'242', %remaining) %,
    jumpl [] =
	machop (%o'321', %remaining) %,
    cai [] =
	machop (%o'300', %remaining) %,
    jsp [] =
	machop (%o'265', %remaining) %,
    blt [] =
	machop (%o'251', %remaining) %,
    jrst [] =
	machop (%o'254', %remaining) %,
    move [] =
	machop (%o'200', %remaining) %,
    movem [] =
	machop (%o'202', %remaining) %,
    sojg [] =
	machop (%o'377', %remaining) %,
    movei [] =
	machop (%o'201', %remaining) %,
    ldb [] =
	machop (%o'135', %remaining) %,
    ildb [] =
	machop (%o'134', %remaining) %,
    idpb [] =
	machop (%o'136', %remaining) %,
    adjbp [] =
	machop (%o'133', %remaining) %,
    hrl [] =
	machop (%o'504', %remaining) %,
    aoj [] =
	machop (%o'340', %remaining) %,
    hlre [] =
	machop (%o'574', %remaining) %,
    idivi [] =
	machop (%o'231', %remaining) %,
    idiv [] =
	machop (%o'230', %remaining) %,
!!    pushj [] =                       			!d501 remove this, it 
!!	machop (%o'260', %remaining) %,                 ! prevents linkage decl
    dmove [] =
	machop (%o'120', %remaining) %,
    dsub [] =
        machop (%o'115', %remaining) %,
    dmovem [] =
	machop (%o'124', %remaining) %,
    fixop [] =
	machop (%o'122', %remaining) %,
    setzb [] =
	machop (%o'403', %remaining) %,
    jump [] =
	machop (%o'320', %remaining) %,
    aos [] =
	machop (%o'350', %remaining) %,
    extend [] =
	machskip (%o'123', %remaining) %;

!+
!
!    *****************************************************************
!    *								     *
!    *			start of extend.bli			     *
!    *							             *
!    *								     *
!    *			contents:				     *
!    *								     *
!    *		1.  macros for use in "extend" instruction	     *
!    *                                                               *
!    *****************************************************************
!
!    author: s. blount
!
!
!-
!+
!
!    *****************************************************************
!    *		various flag values				*
!    *****************************************************************
!
!-

literal
    sflg = bitn (18),				! significance
    abr = bitn (20);				! abort flag

! EXT$k_xxx moved to RMSSYS

!+
!
!    *****************************************************************
!    *		DEFINITIONS FOR AC'S USED IN EXTEND			*
!    *****************************************************************
!
!-

LITERAL
    acfromsize = 0,				! SOURCE SIZE
    acfromadr = 1,				! SOURCE ADDRESS
    actosize = 3,				! DEST SIZE
    actoadr = 4;				! DEST ADDRESS

!+
!
!    *****************************************************************
!    *		BINARY-TO-DECIMAL CONVERSION			*
!    *****************************************************************
!
!-
!<BLF/NOMACRO>
!<BLF/NOFORMAT>
!<BLF/NOERROR>

MACRO
    xiregs =
	REGISTER
	    R1 = 5,
	    R2 = 6,
	    R3 = 7,
	    R4 = 8,
	    R5 = 9
	    %;

MACRO
    xiregs_ea =
	!For Extended addressing, 2-word BPs
	REGISTER
	    R1 = 5,
	    R2 = 6,
	    R3 = 7,
	    R4 = 8,
	    R5 = 9,
	    R6 = 10
	    %;
!<BLF/MACRO>
!<BLF/FORMAT>
!<BLF/ERROR>
%( moved to RMSSYS   !d504
!+
!   Fields for a two-word byte pointer, used
!   either as a single-word or double-word.
!-

FIELD
    ptr$r_fields =
	SET
	ptr$a_local_address = [0, 0, 18, 0],	! Local (18-bit) address
	ptr$v_index_register = [0, 18, 4, 0],	! Index register value
	ptr$v_global_flag = [0, 23, 1, 0],	! Flag for doubleword pointer
	ptr$v_byte_size = [0, 24, 6, 0],	! Byte size
	ptr$v_byte_position = [0, 30, 6, 0],	! Offset of byte
	ptr$a_global_address = [1, 0, 36, 0],	! Global address, also as
	ptr$a_section_address = [1, 0, 18, 0],	!    - address in section
	ptr$v_section_number = [1, 18, 18, 1]	!    - section number
	TES;

LITERAL
    ptr$k_bln = 2;

MACRO
    $byte_pointer =
	BLOCK [ptr$k_bln]

	FIELD
	(ptr$r_fields) %;

)%

!+
!   $COPY_BYTE_POINTER does two double-word moves to move
!   the contents of one 2-word pointer to another.
!-

MACRO
    $copy_byte_pointer (source_ptr, dest_ptr) =
	BEGIN

	REGISTER
	    ac1 = 1,
	    ac2 = 2;

	dmove (ac1, source_ptr);
	dmovem (ac1, dest_ptr);
	END
    %;

!+
!   Extended instruction block for string operations
!-

FIELD
    ext$r_fields =
	SET
	ext$b_opcode = [0, 27, 9, 0],
	ext$a_e1 = [0, 0, 18, 1],
	ext$c_fill = [1, 0, 9, 0]
	TES;

LITERAL
    ext$k_bln = 2;

MACRO
    $extblock =
	BLOCK [ext$k_bln]

	FIELD
	(ext$r_fields) %;

KEYWORDMACRO
    cvtbdo (
	    number,
	    length,
	    string,
	    offset = %C '0',
	    fill = %O '40' ) =
	BEGIN

	REGISTER
	    ac1 = 1,
	    ac2 = 2,
	    ac4 = 4,
	    ac5 = 5,
	    ac6 = 6;

	BUILTIN
	    machop,
	    machskip;

	LOCAL
	    extblk : $extblock INITIAL (0, 0),
	    result;

	extblk [ext$b_opcode] = %O'012';	! CVTBDO code
	extblk [ext$a_e1] = offset;		! Offset to make a character
	extblk [ext$c_fill] = fill;		! Fill character
	dmove (ac1, number);			! Fetch the number
	dmove (ac5, string);			! Fetch the pointer
	ac4 = .length;				! Length to convert
	result = extend (ac1, extblk);		! Do the instruction
	dmovem (ac5, string);			! Retrieve byte pointer
	dmovem (ac1, number);			! Get the number
	length = .ac4;				! Get bytes remaining
	.result					! Return the skip value
	END
    %;

KEYWORDMACRO
    cvtdbo (
	    number,
	    length,
	    string,
	    offset = - %C '0' ) =
	BEGIN

	REGISTER
	    ac1 = 1,
	    ac2 = 2,
	    ac3 = 3,
	    ac4 = 4,
	    ac5 = 5;

	BUILTIN
	    machop,
	    machskip;

	LOCAL
	    extblk : $extblock INITIAL (0, 0),
	    result;

	extblk [ext$b_opcode] = %O'010';	! CVTDBO code
	extblk [ext$a_e1] = offset;		! Offset to make a character
	ac1 = .length;				! Length to convert
	dmove (ac2, string);			! Fetch the pointer
	dmove (ac4, number);			! Fetch the number
	result = extend (ac1, extblk);		! Do the instruction
	dmovem (ac4, number);			! Get the number
	dmovem (ac2, string);			! Retrieve byte pointer
	length = .ac4;				! Get bytes remaining
	.result					! Return the skip value
	END
    %;

MACRO
    moveasciirecord (fromadr, toadr, fromsize, tosize) =
	BEGIN
	xiregs;

	EXTERNAL
	    table1;				! [**3**] ADD EXTERNAL DECLARATION

	LOCAL
	    val,
	    extendblock : VECTOR [3];

	MAP
	    extendblock : BLOCK [1];

	extendblock [0, wrd] = (ext$k_movst^27) + table1;
	extendblock [1, wrd] = 0;
	extendblock [2, wrd] = 0;
	R1 = .fromsize;
	R2 = .fromadr;
	R3 = .0;
	R4 = .tosize;
	R5 = .toadr;
	val = extend (R1, extendblock);
	fromadr = .R2;				! RETURN VALUES
	toadr = .R5;
	fromsize = .R1;
	tosize = .R4;
	.val
	END
    %;

MACRO
    moveasciirecord_ea (fromadr, toadr, fromsize, tosize) =
	BEGIN
	xiregs_ea;

	EXTERNAL
	    table1;				! [**3**] ADD EXTERNAL DECLARATION

	LOCAL
	    val,
	    extendblock : VECTOR [3];

	MAP
	    extendblock : BLOCK [1];

	extendblock [0, wrd] = (ext$k_movst^27) + table1;
	extendblock [1, wrd] = 0;
	extendblock [2, wrd] = 0;
	R1 = .fromsize;
	R2 = .fromadr [0];
	R3 = .fromadr [1];
	R4 = .tosize;
	R5 = .toadr [0];
	R6 = .toadr [1];
	val = extend (R1, extendblock);
	fromadr [0] = .R2;			! RETURN VALUES
	fromadr [1] = .R3;
	toadr [0] = .R5;
	toadr [1] = .R6;
	fromsize = .R1;
	tosize = .R4;
	.val
	END
    %;

!
! XCLEAR - Clear memory extended addressing style
!
                                                                        !a540vv
 MACRO
    xclear (ptr, len) =
	! CLEAR A SERIES OF CORE LOCATIONS
	BEGIN
	
	BIND
	    extendblock = UPLIT (ext$k_xblt^27);

	REGISTER
	    r1 = 1,
	    r2 = 2,
	    r3 = 3;

	
	(ptr) = 0;				! Zero first word
	r1 = (len) - 1;				! Length to clear
	r2 = (ptr);				! Starting address
	r3 = .r2 + 1;				! Copy to here

	IF len GTR 1				! Is XBLT necessary
	THEN
	    extend (r1, extendblock);		! Yes, clear many words


	END
    %;                                                                !a540^^
!+
!
!    *****************************************************************
!    *		DECIMAL-TO-BINARY CONVERSION			*
!    *****************************************************************
!
!-

MACRO
    decimaltobinary (SOURCE, argsize, result) =
	BEGIN
	xiregs;

	LOCAL
	    val;

	BIND
	    extendblock = PLIT (ext$k_cvtdbo^27 + (-char0 AND %O'777777'),
				0,
				0 )	: VECTOR;

	R1 = argsize;
	R2 = SOURCE;
	R3 = 0;
	R4 = 0;
	R5 = 0;
	val = extend (R1, extendblock);
	result = .R5;
	.val
	END
    %;

!+
!
!    *****************************************************************
!    *		COMPARE STRING INSTRUCTIONS				*
!    *****************************************************************
!
!-
!+
!    # OF AC'S TO USE FOR EXTEND INSTRUCTION
!-

LITERAL
    extendacnum = 5;

!+
!    MACRO TO COMPARE TWO STRINGS, SKIP ON LEQ
!-

MACRO
    cstringle (srcadr, destadr, srcsize, destsize) =
	BEGIN
	xiregs;

	LOCAL
	    val;

	BIND
	    csblock = PLIT (ext$k_cmpsle^27,
							0,
							0 )	: VECTOR;

	R1 = .srcsize;				! SET UP AC'S
	R2 = .srcadr;
	R4 = .destsize;
	R5 = .destadr;
	val = extend (R1, csblock);
	destadr = .R5;				! RETURN ADDR AT WHICH COMPARISON STOPPED
	srcadr = .R2;
	.val
	END
    %;

!+
!   MACRO TO COMPARE TWO STRINGS, SKIP ON LEQ ** NON-ZERO SECTION
!   This macro was added as part of edit 407 to RMS v2.
!-

MACRO
    cstringle_ea (srcadr, destadr, srcsize, destsize) =
	BEGIN
	xiregs_ea;

	LOCAL
	    val;

	BIND
	    csblock = PLIT (ext$k_cmpsle^27,
					0,
					0 ) : VECTOR;

	R1 = .srcsize;				! Set up sizes
	R4 = .destsize;				! ...
	dmove (R2, srcadr);			! Load AC pairs
	dmove (R5, destadr);			! ...
	val = extend (R1, csblock);		! Compare the strings
	dmovem (R2, srcadr);			! Return AC pairs
	dmovem (R5, destadr);			! ...
	R6 = R3 = 0;				! Explicitly use ACs	!A425
	.val
	END
    %;

!+
!
!    *****************************************************************
!    *		MOVE-STRING WITH JUSTIFICATION			*
!    *****************************************************************
!
!-

LITERAL
    moveleftacsize = 5,				! NUMBER OF AC'S
    extblksize = 3;				! SIZE OF EXTEND BLOCK

MACRO
    moveleft (fromadr, toadr, fromsize, tosize) =
	BEGIN
	xiregs;

	LOCAL
	    val;

	BIND
	    extendblock = PLIT (ext$k_movslj^27,
						0,
						0 );

	R1 = .fromsize;				! SOURCE STRING SIZE
	R2 = .fromadr;				! SOURCE POINTER
	R4 = .tosize;				! DESTINATION SIZE
	R5 = .toadr;				! DESTINATION PINTER
	val = extend (R1, extendblock);
	fromsize = .R1;				! RETURN VALUES
	fromadr = .R2;
	tosize = .R4;
	toadr = .R5;
	.val
	END
    %;

MACRO
    moveleft_ea (fromadr, toadr, fromsize, tosize) =
	BEGIN
	xiregs_ea;

	LOCAL
	    val;

	BIND
	    extendblock = PLIT (ext$k_movslj^27,
						0,
						0 );

        MAP
           fromadr: VECTOR,             ! in case it is a $byte_pointer !a504
           toadr: VECTOR;               ! in case it is a $byte_pointer !a504

	R1 = .fromsize;				! SOURCE STRING SIZE
	R2 = .fromadr [0];			! SOURCE POINTER
	R3 = .fromadr [1];
	R4 = .tosize;				! DESTINATION SIZE
	R5 = .toadr [0];			! DESTINATION PINTER
	R6 = .toadr [1];
	val = extend (R1, extendblock);
	fromsize = .R1;				! RETURN VALUES
	fromadr [0] = .R2;
	fromadr [1] = .R3;
	tosize = .R4;
	toadr [0] = .R5;
	toadr [1] = .R6;
	.val
	END
    %;

! XCOPY - Copy a block of words, possibly between sections.
!	Do not call unless running in a non-zero section.

MACRO
    xcopy (fromadr, toadr, size) =
	BEGIN

	BIND
	    extendblock = PLIT (ext$k_xblt^27);

	REGISTER
	    tmpac1 = 5,
	    tmpac2 = 6,
	    tmpac3 = 7;

	tmpac1 = size;
	tmpac2 = fromadr;
	tmpac3 = toadr;

	IF .tmpac2<lh> EQL 0 THEN tmpac2 = .tmpac2 OR .rmssec;

	IF .tmpac3<lh> EQL 0 THEN tmpac3 = .tmpac3 OR .rmssec;

	extend (tmpac1, extendblock)
	END
    %;

!+
!   Perform an ADJBP on a 2-word pointer.  This will increment the
!   pointer and return it to its original location, and will work
!   on 2-word blocks containing either 1-word or 2-word byte pointers.
!-

MACRO
    $adjbp_ea (amount, bpointer) =
	BEGIN

	REGISTER
	    ac1 = 1,
	    ac2 = 2;

	ac1 = amount;
	ac2 = 0;
	adjbp (ac1, bpointer);
	dmovem (ac1, bpointer);
	END
    %;

!+
!
!    *****************************************************************
!    *			END OF EXTEND.BLI			*
!    *****************************************************************
!
!-
!+
!
!    ********************************************************************
!    *			START OF F/R/X AB.BLI			   *
!    *								   *
!    *			CONTENTS:				   *
!    *								   *
!    *		1.	SUPPORT INFO FOR USER ARG BLKS		*
!    *								   *
!    ********************************************************************
!
!    AUTHOR: S. BLOUNT
!
!
!-
!+
!    MACROS USED TO ACCESS FAB FIELDS
!-

MACRO
    deferredwrite =
	(.fst [fstfop] AND fopdfw) NEQ 0 %;

!+
!    MACROS USED TO ACCESS RAB FIELDS
!-
!+
!    MACROS FOR MODES OF REFERENCE
!-

MACRO
    movemode =
	(.rab [rabrop, 0] AND roploc) EQL 0 %,
    locatemode =
	(.rab [rabrop, 0] AND roploc) NEQ 0 %;

!+
!    MACROS FOR RECORD-OPTIONS ( ROP )
!-

MACRO
    appendoption =
	(.rab [rabrop, 0] AND ropeof) %,
    readahead =
	(.rab [rabrop, 0] AND roprah) NEQ 0 %,
    writebehind =
	(.rab [rabrop, 0] AND ropwbh) NEQ 0 %;

!+
!    MACROS FOR ADDRESSING-MODES
!-

MACRO
    recordaccess =
	.rab [rabrac, 0] %,
    seqadr =
	( ( .rab [rab$b_rac] EQL rab$k_seq )            !m544
        OR ( .rab [rab$b_rac] EQL rab$k_tra ) )  %,     !m544
    keyadr =
	.rab [rabrac, 0] EQL rackey %,
    rfaadr =
	.rab [rabrac, 0] EQL racrfa %;

!+
!
!    ***********************************************************************
!    *			FORMAT OF KEY SEGMENT DESCRIPTORS	    *
!    ***********************************************************************
!
!-
!+
!    STRUCTURE OF EACH KEY SEGMENT DESCRIPTOR
!-
!+
!    *THE KEY SEGMENT DESCRIPTOR FIELDS ARE NOT NAMED LIKE OTHER
!    FIELDS IN THE XAB. THIS IS BECAUSE THE KEY SEGMENT
!    DESCRIPTORS EXIST IN SEVERAL BLOCKS (XAB,IDB,KDB),
!    AND THEY ARE USUALLY PROCESSED SEPARATELY INSTEAD
!    OF BEING ACCESSED DIRECTLY FROM THE BLOCK. THUS, THESE
!    FIELDS HAVE A GENERIC NAME NOT ASSOCIATED WITH ANY
!    DATA STRUCTURE
!-

MACRO
    keypos =
	lh %,					! POSITION
    keysiz =
	rh %;					! KEY SIZE

!+
!
!    ***********************************************************************
!    *			VALUES FOR KEY XAB FIELDS		   	*
!    ***********************************************************************
!
!-
!+
!    BYTE SIZES FOR EACH DATA-TYPE
!-

LITERAL
    stringbytesize = 7,				! STRING
    ebcdicbytesize = 9,				! EBCDIC
    sixbitbytesize = 6,				! SIXBIT KEYS
    packedbytesize = 9,                         ! PACKED DECIMAL KEYS !A411
    IN4bytesize    = 36,                        ! INTEGER KEYS        !A411
    FL1bytesize    = 36,                        ! FLOATING KEYS       !A411
    FL2bytesize    = 36,                        ! DOUBLE FLOAT KEYS   !A411
    GFLbytesize    = 36,                        ! GFLOAT KEYS         !A411
    in8bytesize    = 36,                        ! DOUBLE INTEGER KEYS !A411
    as8bytesize    = 9,                         ! ANSI ASCII          !A411
    un4bytesize    = 36;                        ! Unsigned Integer    !A411

!+
!    Datatype definitions for RMSUTL use (added in edit 455)
!-
LITERAL
    dtp$k_six = 0,		! SIXBIT data type
    dtp$k_asc = 1,		! ASCII data type
    dtp$k_ebc = 2,		! EBCDIC data type
    dtp$k_pac = 3,		! PACKED decimal datatype
    dtp$k_in4 = 4,		! INTEGER datatype
    dtp$k_fl1 = 5,		! FLOAT datatype
    dtp$k_fl2 = 6,		! DOUBLE FLOAT datatype
    dtp$k_gfl = 7,		! GFLOAT datatype
    dtp$k_in8 = 8,		! DOUBLE INTEGER datatype
    dtp$k_as8 = 9,		! 8-bit ASCII
    dtp$k_un4 = 10;		! Unsigned Integer


!+
!    KEY OF REFERENCE SYMBOL VALUES
!-

LITERAL
    refprimary = 0;				! PRIMARY KEY

!+
!    SIZE OF THE KEY-NAME STRING IN WORDS (30 BYTES)
!-

LITERAL
    keynamesize = 7;				! 7 WORDS

!+  610
!   AND IN BYTES
!-

LITERAL
    Knmcharsiz = 30;				! 30 BYTES

!+
!
!    ***********************************************************************
!    *			STRUCTURE OF DATA-TYPE DESCRIPTOR TABLE	    *
!    ***********************************************************************
!
!-
!+
!    STRUCTURE OF DATA-TYPE DESCRIPTOR TABLE
!-

MACRO
    dtpbytesize =
	rh %;					! ONLY ONE FIELD SO FAR

!+
!    ****************	END OF -AB.REQ	*****************
!-
!+
!
!    ********************************************************
!    *							*
!    *		START OF FILES.REQ			*
!    *							*
!    *		CONTENTS:				*
!    *							*
!    *		1. BLOCK-TYPE DEFINITIONS		*
!    *		2. BLOCK FORMAT DEFINITIONS		*
!    *		3. RECORD FORMAT DEFINITIONS		*
!    *							*
!    *********************************************************
!
!    AUTHOR: S. BLOUNT
!
!
!-
!+
!    EACH RMS-20 FILE BEGINS WITH A "FILE PROLOGUE BLOCK" WHICH
!    CONTAINS ALL INFORMATION (SUCH AS FILE ORGANIZATION, RECORD
!    FORMAT, ETC.) THAT IS COMMON TO ALL TYPES OF RMS-20 FILES.
!    THIS BLOCK IS CREATED WHEN A $CREATE IS ISSUED, AND IS
!    READ IN AND PROCESSED WHEN THE FILE IS OPENED.
!
!    FOR SEQUENTIAL AND RELATIVE FILES, THIS BLOCK IS THE ONLY
!    ONE CONTAINED IN THE ENTIRE FILE PROLOGUE (WITH THE EXCEPTION
!    OF A 1-WORD BLOCK INDICATING THE END OF THE FILE HEADER).
!
!    FOR INDEXED AND DIRECT FILES, THERE MAY BE OTHER BLOCKS (SUCH AS THE INDEX
!    DESCRIPTOR BLOCK, AREA DESCRIPTOR BLOCK, ETC. ). THE
!    DEFINITIONS OF THESE OTHER BLOCKS ARE CONTAINED IN THE
!    FILE "XFILES.REQ".
!
!    THE GENERAL STRUCTURE OF THE FILE HEADER FOR AN RMS-20
!    FILE IS AS FOLLOWS:
!
!    !=====================================!
!    !                                     !
!    !         FILE PROLOGUE BLOCK         !
!    !                                     !
!    !                                     !
!    !-------------------------------------!
!    !          AREA DESCRIPTORS           !
!    !           (INDEXED ONLY)            !
!    !-------------------------------------!
!    !                                     !
!    !         INDEX DESCRIPTOR #0         !
!    !           (INDEXED ONLY)            !
!    !-------------------------------------!
!    !                                     !
!    !         INDEX DESCRIPTOR #1         !
!    !           (INDEXED ONLY)            !
!    !-------------------------------------!
!    !                 .                   !
!    !                 .                   !
!    !-------------------------------------!
!    !                                     !
!    !         INDEX DESCRIPTOR #N         !
!    !                                     !
!    !-------------------------------------!
!    !    END BLOCK (NON-INDEXED ONLY)     !
!    !=====================================!
!
!
!
!    FORMAT OF THE FILE PROLOGUE BLOCK
!    =================================
!
!    !-------------------------------------!
!    !       BID        !       BLN        !
!    !-------------------------------------!
!    !   <**>   !  RFM  ! BSZ !  BKS  !ORG !
!    !-------------------------------------!
!    !       RAT        !       MRS        !
!    !-------------------------------------!
!    !                 MRN                 !
!    !-------------------------------------!
!    !     <UNUSED>     !     NEXTBKT      !
!    !-------------------------------------!
!    ! AREAS  !ADBOFFSET!  KEYS  !IDBOFFSET!
!    !-------------------------------------!
!    !             <RESERVED>              !
!    !-------------------------------------!
!    !             <RESERVED>              !
!    !-------------------------------------!
!    !             <RESERVED>              !
!    !-------------------------------------!
!    !             <RESERVED>              !
!    !-------------------------------------!
!    !             <RESERVED>              !
!    !-------------------------------------!
!    !             <RESERVED>              !
!    !-------------------------------------!
!    !             <RESERVED>              !
!    !-------------------------------------!
!
!
!
!
!    FIELDS IN THE FILE PROLOGUE BLOCK
!    =================================
!
!    FIELD		FUNCTION
!    =====		========
!
!    BID		BLOCK-ID OF THE FILE PROLOGUE BLOCK
!
!    BLN		LENGTH OF THE FILE PROLOGUE BLOCK
!
!    RFM		RECORD FORMAT
!
!    BSZ		BYTE SIZE OF FILE.
!
!    BKS		DEFAULT BUCKET SIZE FOR INDEXED FILES.
!
!    ORG		FILE ORGANIZATION.
!
!    RAT		RECORD ATTRIBUTES
!
!    MRS		MAXIMUM RECORD SIZE.
!
!    MRN		MAXIMUM RECORD NUMBER (RELATIVE FILES ONLY).
!
!    NEXTBKT		NEXT BUCKET AVAILABLE FOR ALLOCATION.
!    USED ONLY FOR INDEXED FILES, THIS FIELD CONTAINS
!    THE ABSOLUTE PAGE NUMBER OF THE NEXT BUCKET WHICH
!    CAN BE ALLOCATED FOR INDEX OR DATA RECORDS.
!
!    AREAS		NUMBER OF FILE AREAS (INDEXED ONLY).
!
!    ADBOFFSET	OFFSET INTO PROLOGUE PAGE OF FIRST AREA DESCRIPTOR BLOCK.
!
!    KEYS		NUMBER OF KEYS DEFINED FOR FILE (INDEXED ONLY).
!
!    IDBOFFSET	OFFSET INTO PROLOGUE PAGE OF FIRST INDEX DESCRIPTOR BLOCK.
!
!    <ALL OTHER FIELDS ARE RESERVED>
!
!
!-
!+
!
!    ****************************************************************
!    *			BLOCK-TYPE DEFINITIONS			*
!    *****************************************************************
!
!-
!+
!    BLOCK-TYPE FOR RMS-20 FILE PROLOGUES
!-

LITERAL
    fpblock = %O'1757',				! FILE PROLOGUE BLOCK
    endblock = %O'1777',			! END BLOCK
    endblocksize = %O'1';			! SIZE OF END BLOCK

!+
!
!    *****************************************************************
!    *			FILE-PROLOGUE BLOCK STRUCTURE		*
!    *****************************************************************
!
!-
!+
!    BLOCK AND PAGE NUMBERS OF FILE PROLOGUE TABLE
!-

LITERAL
    fptblockno = 0,				! BLOCK NUMBER OF FPT
    fptpageno = 0;				! PAGE NUMBER OF FPT

!+
!    SIZE OF FILE-PROLOGUE BLOCK
!-

LITERAL
    fptsize = 13;				! BLOCK SIZE

!+
!    STRUCTURE DEFINITIONS
!-

MACRO 						!BLOCKTYPE = 0,LH$,			! BLOCK-TYPE
    !BLOCKSIZE = 0,RH$,			! BLOCK SIZE
    ! **BITS 0-12 OF WORD 1 ARE UNUSED**
    fptrfm =
	1, 18, 5, 0 %,				! RECORD FORMAT
    fptbsz =
	1, 12, 6, 0 %,				! BYTE SIZE
    fptbks =
	1, 4, 8, 0 %,				! BUCKET SIZE
    fptorg =
	1, 0, 4, 0 %,				! FILE ORGANIZATION
    fptrat =
	2, lh %,				! RECORD ATTRIBUTES
    fptmrs =
	2, rh %,				! MAX RECORD SIZE
    fptmrn =
	3, wrd %,				! MAX RECORD NUMBER
    fptnxtbkt =
	4, rh %,				! NEXT BUCKET (INDEXED FILES)
    fptareas =
	5, 27, 9, 0 %,				! # OF FILE AREAS
    fptadb =
	5, 18, 9, 0 %,				! OFFSET TO 1ST AREA DESC
    fptkeys =
	5, 9, 9, 0 %,				! # OF KEYS
    fptidb =
	5, 0, 9, 0 %,				! OFFSET TO 1ST INDEX DESC
    fptrs1 =
	6, wrd %,				! <RESERVED>
    fptrs2 =
	7, wrd %,				! <RESERVED>
    fptrs3 =
	8, wrd %,				! <RESERVED>
    fptrs4 =
	9, wrd %,				! <RESERVED>
    fptrs5 =
	10, wrd %,				! <RESERVED>
    fptrs6 =
	11, wrd %,				! <RESERVED>
    fptrs7 =
	12, wrd %;				! <RESERVED>

!+
!
!    ****************************************************************
!    *			RECORD FORMAT DEFINITIONS		*
!    *****************************************************************
!
!-
!+
!    FORMAT OF A RECORD HEADER IN A SEQUENTIAL/RELATIVE FILE:
!
!    +-------------------------------------+
!    !FLGS!  <UNUSED>   !   RECORD SIZE    !
!    +-------------------------------------+
!
!
!-
!+
!    STRUCTURES FOR RECORD HEADER
!-

MACRO
    rhdrsize =
	0, rh %,				! Byte count of record
    rhdrundef =
	0, 18, 16, 0 %;				! This field is

						!   currently undefined
!+
!    FLAG BITS IN THE RECORD HEADER OF SEQUENTIAL/RELATIVE FILES
!-

LITERAL
    rhdrvalid = bitn (0),			! VALID BIT
    rhdrdelete = bitn (1);			! RECORD IS DELETED

!+
!
!    ****************************************************************
!    *			MISCELLANEOUS DEFINITIONS		*
!    *****************************************************************
!
!-

LITERAL
    ofsetmask = %O'777',			! MASK TO GET OFFSET INTO PAGE
    headersize = 1,				! DEFAULT HEADER SIZE FOR RECORDS
    rmsbytesize = 36,				! BYTE SIZE FOR READING FILE
    eopmarker = -1,				! MARKER TO DENOTE END-OF-PAGE FOR "BLK" FILES
    maxlsn = 99999,				! MAX LINE-NUMBER FOR LSA FILES
    asciibytesize = 7,				! BYTE SIZE FOR ASCII FILES
    asciibytperword = 36/asciibytesize;		! # OF ASCII BYTES IN EACH WORD

LITERAL
    ch_in_p = asciibytperword*pagesize,
    wd_in_p = pagesize;

!+
!
!    *****************************************************************
!    *		STRUCTURE OF RECORD-FILE ADDRESS ( RFA )	*
!    *****************************************************************
!
!-
!+
!    RFA FOR SEQUENTIAL FILES
!-

MACRO
    rfapage =
	0, 9, 18, 0 %;				! Page number of file page

!+
!
!    ****************************************************************
!    *			END OF FILES.REQ			*
!    *****************************************************************
!
!-
!+
!
!    ******************************************************************
!    *			START OF FST.REQ			   *
!    *								   *
!    *			CONTENTS:				   *
!    *								   *
!    *		1.	STRUCTURES FOR FILE STATUS TABLE	   *
!    *								   *
!    *******************************************************************
!
!    AUTHOR: S. BLOUNT
!
!
!-
!+
!    THE FILE STATUS TABLE (FST) IS THE PRIMARY INTERNAL
!    RMS-20 DATA STRUCTURE WHICH REPRESENTS ALL INFORMATION
!    OF IMPORTANCE TO THE CORRECT PROCESSING OF THE FILE.
!    THE FST CAN BE THOUGHT OF AS BEING THE "INTERNAL FAB".
!    AN FST IS ALLOCATED WHEN THE FILE IS OPENED AND DE-ALLOCATED
!    ONLY WHEN THE FILE IS CLOSED. THERE IS ONLY ONE FST PER FILE,
!    PER PROCESS, REGARDLESS OF HOW MANY RECORD STREAMS MAY BECOME
!    ACTIVE ON THE FILE.
!
!    THE FORMAT OF THE FST IS AS FOLLOWS:
!
!    +-------------------------------------+
!    !       BID        !       BLN        !
!    !-------------------------------------!
!    !      BLINK       !      FLINK       !
!    !-------------------------------------!
!    !       ADB        !       JFN        !
!    !-------------------------------------!
!    !       ORG        !     SEQBKT       !
!    !-------------------------------------!
!    !     DEVTYPE      !      FLAGS       !
!    !-------------------------------------!
!    !  FAC   !   SHR   !       RFM        !
!    !-------------------------------------!
!    !MIN!NUMBUFF!BUFF- !       MRS        !
!    !BUF!       ! SIZE !                  !
!    !-------------------------------------!
!    ! LOBYTE !           UNUSED           !
!    !-------------------------------------!
!    !                 MRN                 !
!    !-------------------------------------!
!    !       KDB        !KBFSZ!    FOP     !
!    !-------------------------------------!
!    !       RAT        !       BSZ        !
!    !-------------------------------------!
!    !		DATELASTACC	           !
!    !-------------------------------------!
!    !		CREATIME	           !
!    !-------------------------------------!
!    !		SIZEOFFILE	           !
!    +-------------------------------------+
!
!
!
!
!    FIELDS WITHIN THE FILE STATUS TABLE
!    ===================================
!
!    FIELD		FUNCTION
!    =====		========
!
!    BID		BLOCK ID OF AN FST
!
!    BLN		LENGTH OF AN FST
!
!    BLINK		BACKWARD LINK TO LAST RST IN CHAIN
!
!    FLINK		FORWARD LINK TO FIRST RST IN CHAIN
!
!    JFN		JFN OF FILE
!
!    ORG		ORGANIZATION OF FILE
!
!    DEVTYPE		DEVICE TYPE CODE (AS RETURNED BY MONITOR)
!
!    FLAGS		PROCESSING FLAGS:
!
!    FLGTRUNC	A $TRUNCATE WAS DONE ON THIS STREAM
!    FLGFLOCKED	FILE IS LOCKED (BY OPEN)
!    FLGUNDEF	FILE IS CURRENTLY IN UNDEFINED STATE (UNUSED)
!    FLGNEWFILE	FILE IS BEING CREATED
!    FLGILOCKED	INDEX SEARCH CAPABILITY IS LOCKED
!    FLGREO		FILE SHOULD BE RE-ORGANIZED
!
!    FAC		USER'S FAC VALUE
!
!    SHR		USER'S SHR VALUE
!
!    RFM		RECORD FORMAT (NOTE 1/2 WORD FOR SPEED)
!
!    MINBUF		MIN. NUMBER OF BUFFERS REQUIRED FOR FILE
!
!    NUMBUFF		NUMBER OF BUFFERS WHICH SHOULD BE ALLOCATED
!
!    BUFFSIZE	SIZE IN PAGES OF EACH BUFFER
!
!    MRS		MAXIMUM RECORD SIZE
!
!    LOBYTE		WORD NUMBER OF FIRST DATA WORD IN FILE (WORD AFTER HEADER)
!
!    MRN		MAXIMUM RECORD NUMBER
!
!    KDB		ADDRESS OF KEY DESCRIPTOR BLOCK (INDEXED ONLY)
!
!    KBFSIZE		SIZE IN WORDS OF KEY BUFFER REQUIRED TO HOLD LARGEST KEY
!
!    FOP		FILE OPTIONS (NOT USED)
!
!    RAT		RECORD ATTRIBUTES
!
!    BSZ		BYTE SIZE (NOTE SIZE FOR SPEED)
!
!-
!+
!
!    ***********************************************************************
!    *			FILE STATUS TABLE STRUCTURES		      *
!    ***********************************************************************
!
!-
!+
!    NOTE THAT IF THE FST, THERE ARE CERTAIN FIELDS WHICH
!    ARE SMALLER IN SIZE THAN THE AMOUNT OF STORAGE (# OF BITS)
!    WHICH ARE USED TO CONTAIN THEM. FOR EXAMPLE, THE BSZ
!    FIELD IN THE FAB IS 6 BITS WIDE, BUT IS KEPT IN 18
!    BITS IN THE FST. THIS IS BECAUSE FOR ALL BYTE ACCESSES,
!    A LDB OPERATION AND A BYTE POINTER WORD ARE NECESSARY
!    FOR EACH SUCH ACCESS. IF THE SAME DATA IS STORED IN A
!    HALF-WORD, 1 INSTRUCTION CAN ACCESS IT AND NO BYTE
!    POINTER IS NECESSARY. THUS, ALL COMMONLY-USED FIELDS
!    ARE STORED IN HALF-WORDS TO SPEED UP ACCESS.
!-

LITERAL
    fstcode = 3,				! BLOCK-TYPE FOR FST

%IF %SWITCHES(TOPS20)                                                     !m572
%THEN
    fstsize = 16;                               ! LENGTH OF AN FST
%ELSE
    fstsize = 17;                               ! LENGTH OF AN FST
%FI

MACRO 						!BLOCKTYPE = 0,LH$,		! BLOCK-TYPE CODE
    !BLOCKLENGTH = 0,RH$,		! BLOCK-LENGTH
    !BLINK = 1,LH$,			! BACK POINTER TO LAST RST
    !FLINK = 1,RH$, 		! FORWARD PTR TO NEXT RST
    fstadb =
	2, lh %,				! PTR TO FILE'S AREA DESCRIPTOR
    fstjfn =
	2, rh %,				! JFN OF FILE
    fstorg =
	3, lh %,				! FILE ORGANIZATION
    fstseqbkt =
	3, rh %,				! BKT FILE IS POSIT AT
    fstdevtype =
	4, lh %,				! DEVICE FLAGS (FROM DVCHR)
    fstflags =
	4, rh %,				! PROCESSING FLAGS
    fstfac =
	5, 27, 9, 0 %,				! FILE ACCESS
    fstshr =
	5, 18, 9, 0 %,				! SHARE ACCESS
    fstrfm =
	5, rh %,				! RECORD FORMAT
    fstminbuf =
	6, 33, 3, 0 %,				! MIN. BUFFERS TO ALLOCATE
    fstnumbuf =
	6, 24, 9, 0 %,				! BUFFERS TO TRY TO ALLOCATE
    fstbufsiz =
	6, 18, 6, 0 %,				! SIZE OF A BUFFER (IN PAGES)
    fstmrs =
	6, rh %,				! MAX RECORD SIZE
    fstlobyte =
	7, 27, 9, 0 %,				! FIRST BYTE OF RECORD DATA
!****BITS 0-27 ARE UNUSED
    fstmrn =
	8, wrd %,				! MAX RECORD NUMBER
    fstkdb =
	9, lh %,				! ADDRESS OF 1ST KEY BLOCK
    fstkbfsize =
	9, 10, 8, 0 %,				! SIZE OF KEY BUFFER (IN WORDS)
    fstfop =
	9, 0, 10, 0 %,				! OPTIONS USED ON OPEN
    fstrat =
	10, lh %,				! RECORD ATTRIBUTES
    fstbsz =
	10, rh %,				! FILE BYTE SIZE
    						! NON-0 ON 10 ONLY
    fstdla =
	11, wrd %,				! DATE FILE WAS LAST ACCESSED
    fstct =
	12, wrd %,				! TIME OF CREATION OF FILE
    fstsof =
	13, wrd %;				! SIZE OF FILE IN WORDS

!+
!    Minimum number of buffers for various file organizations
!-

LITERAL
    minbufasc = 1,				! ASCII file organization
    minbufseq = 1,				! Sequential file organization
    minbufrel = 1,				! Relative file organization
    minbufidx = 3;				! Indexed file organization

!+
!    Default number of buffers for various file organizations
!-

LITERAL
    numbufasc = 1,				! ASCII file organizations
    numbufseq = 2,				! Sequential file organization
    numbufrel = 2,				! Relative file organization
    numbufidx = 3;				! Indexed (+ number of levels)

!+
!    VALUES OF BUFSIZ FIELD FOR VARIOUS FILE ORGANIZATIONS
!-

LITERAL
    defbufsiz = 1;				! DEFAULT BUFFER SIZE

!+
!    MACROS FOR ACCESSING FILE ORGANIZATION
!-

MACRO
    fileorg =
	.fst [fstorg] %,
    rmsfile =
	(.fst [fstorg] GTR orgasc) %,		! THIS IS A RMS-FILE
    nonrmsfile =
	(.fst [fstorg] EQL orgasc) %,		! THIS IS not an RMS FILE !a504
    asciifile =
	(.fst [fstorg] EQL orgasc) %,		! THIS IS AN ASCII-FILE (maybe)
    seqfile =
	(.fst [fstorg] EQL orgseq) %,
    relfile =
	(.fst [fstorg] EQL orgrel) %,
    idxfile =
	(fileorg EQL orgidx) %;

!+
!    MACROS FOR ACCESSING RECORD FORMATS
!-

MACRO
    variablerlength =
	.fst [fstrfm] EQL rfmvar %,
    fixedlength =
	(.fst [fstrfm] EQL rfmfix) %,
    stream =
	.fst [fstrfm] EQL rfmstm %,		! ASCII STREAM RECORDS
    sequenced =
	.fst [fstrfm] EQL rfmlsa %;

!+
!    MACROS FOR DETERMINING DEVICE-TYPE
!-

MACRO
    dasd =
	(.fst [fstdevtype] EQL dvdsk) %,	! DISK DEVICE
    mta =
	(.fst [fstdevtype] EQL dvmta) %,	! MAGTAPE
! LPT is one of the obsolete calling macros, use LLPT until further notice
    llpt =
	(.fst [fstdevtype] EQL dvlpt) %,	! Line Printer
    tty =
	(.fst [fstdevtype] EQL dvtty) %,	! TTY DEVICE
    qing =
	(.fst [fstflags] AND flgqing) %,	! Q'ING IS DONE TO FILE
    blocked =
	(.fst [fstrat] AND ratblk) NEQ 0 %;

!+
!    MACROS FOR PROCESSING-MODE
!-

MACRO
    inputmode =
	(.fst [fstfac] AND axwrt) EQL 0 %,
    outputmode =
	(.fst [fstfac] AND axwrt) NEQ 0 %,
    iomode =
	((.fst [fstfac] AND (axget + axput)) EQL (axget + axput)) %,
    updatemode =
	(.fst [fstfac] AND (axdel + axupd)) NEQ 0 %;

!+
!    MACROS TO ACCESS USER/CONNCURENT ACCESS FIELDS
!-

MACRO
    fileaccess =
	.fst [fstfac] %,
    shareaccess =
	.fst [fstshr] %;

!+
!    FLAGS USED IN FST FLAG WORD
!    ***NOTE THAT BIT 35 IS UNUSED***
!-

LITERAL
    flglocking = bitn (34),			! RECORDS ARE BEING LOCKED
    flgflocked = bitn (33),			! FILE IS LOCKED
    flgundef = bitn (32),			! FILE IS IN UNDEFINED STATE
    flgnewfile = bitn (31),			! THIS IS A NEW FILE
    flgilocked = bitn (29),			! INDEX STRUCTURE IS LOCKED
    flgreo = bitn (28);				! FILE SHOULD BE RE-ORGANIZED

!+
!    MACROS USED TO ACCESS FST FLAGS
!-

MACRO
    filelocked =
	(.fst [fstflags] AND flgflocked) NEQ 0 %,
    locking =
	(.fst [fstflags] AND flglocking) NEQ 0 %,
    newfile =
	(.fst [fstflags] AND flgnewfile) NEQ 0 %,
    indexlocked =
	(.fst [fstflags] AND flgilocked) NEQ 0 %;

!+
!    ****************	END OF FST.REQ	*****************
!-
!+
!
!    ******************************************************************
!    *			START OF HEADER.REQ			   *
!    *								   *
!    *			CONTENTS:				   *
!    *								   *
!    *		1.	STRUCTURE OF BLOCK HEADER		   *
!    *								   *
!    *******************************************************************
!
!    AUTHOR: S. BLOUNT
!
!
!-
!+
!    ALL INTERNAL DATA STRUCTURES WITHIN RMS-20 HAVE
!    BASICALLY THE SAME FORMAT: A FIXED-LENGTH BLOCK
!    HEADER FOLLOWED BY A VARIABLE-LENGTH AREA WHICH
!    IS UNIQUE TO EACH BLOCK.  THE FIELDS WITHIN THE
!    THE BLOCK HEADER ARE NAMED IDENTICALLY FOR ALL
!    BLOCKS.  THE FIELDS WHICH ARE SPECIFIC TO EACH
!    BLOCK ARE NAMED BY A 3-CHARACTER BLOCK NAME CODE
!    FOLLOWED BY A FIELD-NAME ( E.G., "FABORG" DENOTES
!    THE ORG FIELD OF THE FAB ).
!
!    THE FIELDS WHICH COMPRISE THE FIXED-LENGTH HEADER
!    ARE ARE FOLLOWS:
!
!    BLOCKTYPE		CODE WHICH IDENTIFIES THE BLOCK
!
!    BLOCKLENGTH		SIZE IN WORDS OF BLOCK
!
!    BLINK			BACKWARDS LINK ( RST AND FST )
!
!    FLINK			FORWARDS LINK ( RST AND FST )
!
!    STATUS			USER STATUS CODE ( FAB AND RAB )
!
!    STATUSVALUE		USER STATUS-VALUE CODE ( FAB AND RAB )
!
!
!
!-
!** [10] Add space fix to macros, JMT, 28-Feb-78

MACRO
    blocktype =
	0, 18, 18, 0 %,				! BLOCK-TYPE CODE
    blocklength =
	0, 0, 18, 0 %,				! LENGTH OF BLOCK
    status =
	1, 18, 18, 0 %,				! STATUS CODE
    statusvalue =
	1, 0, 18, 0 %,				! ADDITIONAL STATUS INFO
    blink =
	1, lh %,				! BACK LINK TO LAST BLOCK ON CHAIN
    flink =
	1, rh %;				! FORWARD LINK ON CHAIN

!+
!    MISCELLANEOUS VALUES AND MACROS FOR THE BLOCK HEADER
!-

MACRO
    blockheader =
	0, wrd %;				! THE ENTIRE HEADER WORD

LITERAL
    blktypelsh = 18;				! SHIFTING CONSTANT FOR BLOCK-TYPE

!+
!    MACROS TO LINK AND REMOVE A BLOCK (RST) FROM
!    A CHAIN OF OTHER BLOCKS
!-

MACRO
    link (newblock, oldblock) =
	BEGIN

	REGISTER
	    tempadr : REF BLOCK;

	tempadr = .oldblock [blink];		! GET BACK LINK
	oldblock [blink] = .newblock;		! POINT BACK TO THIS ONE
	newblock [flink] = .oldblock;
	tempadr [flink] = .newblock;		! POINT TO THIS ONE
	newblock [blink] = .tempadr
	END
    %;

!+
!    MACRO TO REMOVE A BLOCK FROM A CHAIN
!-

MACRO
    delink (thisblock) =
	BEGIN

	REGISTER
	    tempadr1 : REF BLOCK,
	    tempadr2 : REF BLOCK;

	tempadr1 = .thisblock [blink];		! GET BACK LINK
	tempadr2 = .thisblock [flink];		! AND FORWARD LINK
	tempadr1 [flink] = .tempadr2;		! RELINK CHAIN
	tempadr2 [blink] = .tempadr1
	END
    %;

!+
!    **********	END OF HEADER.REQ	*************
!-
!+
!
!    ******************************************************************
!    *			START OF KDB.REQ			   *
!    *								   *
!    *			CONTENTS:				   *
!    *								   *
!    *		1. STRUCTURE OF KEY DESCRIPTOR BLOCK		   *
!
!    *								   *
!    *******************************************************************
!
!    AUTHOR: S. BLOUNT
!
!
!-
!+
!    THIS FILE CONTAINS ALL THE STRUCTURES AND DEFINITIONS
!    FOR THE KEY DESCRIPTOR BLOCKS USED TO PROCESS AN
!    INDEXED FILE. THESE BLOCKS (CALLED KDB'S) ARE CREATED
!    IN FREE CORE WHEN AN INDEXED FILE IS INITIALLY OPENED
!    OR CREATED.  EACH KDB CONTAINS A SUMMARY OF THE INFORMATION
!    ABOUT THE INDEX CHARACTERISTICS WHICH IS KEPT IN THE
!    FILE PROLOGUE.  SUCH CHARACTERISTICS AS THE KEY-NAME
!    AND THE FIRST DATA BUCKET NUMBER ARE NOT MAINTAINED
!    IN CORE BECAUSE THEY ARE SO SELDOM NEEDED.  THERE ARE
!    ALSO SOME FIELDS IN THE KDB ( E.G., DATA RECORD HEADER
!    SIZE) WHICH ARE COMPUTED DYNAMICALLY WHEN THE KDB IS
!    INITIALLY CREATED.
!
!    THE KDB'S ARE LINKED TOGETHER AND THE FIRST ONE (I.E.
!    THE KDB FOR THE PRIMARY KEY) IS POINTED TO BY A FIELD
!    IN THE FILE-STATUS TABLE. THE LINK OF THE LAST KDB IS
!    NUL TO INDICATE THE END OF THE CHAIN.
!
!    THE KDB'S REMAIN IN FREE CORE FOR THE DURATION OF THE
!    PROCESSING OF THE FILE. THEY ARE FLUSHED ONLY WHEN THE
!    FILE IS CLOSED.
!
!
!
!
!-
!+
!    FORMAT OF THE KEY DESCRIPTOR BLOCK:
!    ===================================
!
!
!    !=====================================!
!    !       BID        !       BLN        !
!    !-------------------------------------!
!    !       ROOT       !       REF        !
!    !-------------------------------------!
!    !HSZ! DTP !        IDB-ADDRESS        !
!    !-------------------------------------!
!    !      FLAGS       !    NXT (KDB)     !
!    !-------------------------------------!
!    !  IBKZ  !  DBKZ   !  IAN   !   DAN   !
!    !-------------------------------------!
!    !<**> !KBSZ !LEVELS!      MINRSZ      !
!    !-------------------------------------!
!    !    IFLOFFSET     !    DFLOFFSET     !
!    !-------------------------------------!
!    !       KSZ        !       KSZW       !
!    !-------------------------------------!
!    !       POS0       !       SIZ0       !
!    !-------------------------------------!
!    !                  .                  !
!    !                  .                  !
!    !-------------------------------------!
!    !       POS7       !       SIZ7       !
!    !=====================================!
!
!-
!+
!
!    FIELDS IN KEY DESCRIPTOR BLOCK
!    ==============================
!
!    FIELDS		FUNCTION
!    ======		========
!
!    BID		BLOCK ID OF KDB
!
!    BLN		LENGTH OF KDB
!
!    ROOT		ROOT BUCKET
!
!    REF		KEY OF REFERENCE
!
!    HSZ		SIZE OF HEADER (VAR=3,FIX=2,SIDR=2)
!
!    DTP		DATA-TYPE
!
!    IDBADDR		WORD ADDRESS OF IDB IN FILE
!
!    FLAGS		PROCESSING FLAGS
!    FLGNOINDEX	NO INDEX EXISTS FOR THIS KEY
!    FLGDIDCHANGE	THIS KEY DID CHANGE ON THIS $UPDATE
!    <ALL XAB FLAGS>
!
!    NXT		ADDRESS OF NEXT KDB
!
!    IBKZ		INDEX BUCKET SIZE
!
!    DBKZ		DATA BUCKET SIZE
!
!    IAN		INDEX AREA NUMBER (NOT USED)
!
!    DAN		DATA AREA NUMBER (NOT USED)
!
!    KBSZ		BYTE SIZE OF KEY
!
!    LEVELS		NUMBER OF LEVELS IN INDEX
!
!    MINRSZ		MIN RECORD SIZE TO ENCLOSE THIS KEY
!
!    IFLOFFSET	INDEX FILL OFFSET
!
!    DFLOFFSET	DATA FILL OFFSET
!
!    KSZ		SIZE OF KEY IN BYTES
!
!    KSZW		SIZE OF KEY IN WORDS (NOTE SIZE FOR SPEED)
!
!    POS0,SIZ0	KEY SEGMENTS DESCRIPTORS
!    .
!    .
!    .
!
!
!-
!+
!
!    ***********************************************************************
!    *			STRUCTURE OF KEY DESCRIPTOR BLOCK	     *
!    ***********************************************************************
!
!-
!+
!    SIZE VALUES FOR THE KDB'S
!-

LITERAL
    kdbcode = 6,				! BLOCK-TYPE CODE FOR KDB
    kdbsize = 8 + maxkeysegs;			! FIXED PART + KEY SEGMENTS

MACRO 						!BLOCKLENGTH	=	0,LH$,		! KDB BLOCK-TYPE
    !BLOCKLENGTH	=	0,RH$,		! SIZE OF THE KDB
    kdbroot =
	1, lh %,				! ROOT BUCKET NUMBER
    kdbref =
	1, rh %,				! KEY OF REFERENCE
    kdbhsz =
	2, 33, 3, 0 %,				! SIZE OF HEADER
    kdbdtp =
	2, 27, 6, 0 %,				! DATA-TYPE OF KEY
    kdbidbaddr =
	2, 0, 27, 0 %,				! DISK ADDRESS OF RELEATED IDB
    kdbflags =
	3, lh %,				! FLAGS (FROM XAB)
    kdbnxt =
	3, rh %,				! LINK TO NEXT KDB
    kdbibkz =
	4, 27, 9, 0 %,				! INDEX BUCKET SIZE
    kdbdbkz =
	4, 18, 9, 0 %,				! DATA BUCKET SIZE
    kdbian =
	4, 9, 9, 0 %,				! INDEX AREA NUMBER (FROM XAB)
    kdbdan =
	4, 0, 9, 0 %,				! DATA AREA NUMBER (FROM XAB)
! **BITS 0-5 OF WORD 5 ARE UNUSED**
    kdbkbsz =
	5, 24, 6, 0 %,				! BYTE SIZE OF KEY
    kdblevels =
	5, 18, 6, 0 %,				! # OF LEVELS IN INDEX
    kdbminrsz =
	5, rh %,				! MIN RSZ TO INCLUDE THIS KEY
    kdbifloffset =
	6, lh %,				! OFFSET FOR IFL
    kdbdfloffset =
	6, rh %,				! OFFSET FOR DFL
    kdbksz =
	7, lh %,				! TOTAL SIZE OF KEY (BYTES)
    kdbkszw =
	7, rh %;				! SIZE OF KEY IN WORDS

!+
!    FOLLOWING THESE FIXED FIELDS COMES THE LIST OF KEY SEGMENT
!    DESCRIPTORS. THE FORMAT OF THESE IS THE SAME AS DEFINED IN
!    THE XAB. THEREFORE, SEE "XAB.REQ" FOR THEIR STRUCTURE
!-

LITERAL
    kdbksdoffset = kdbsize - maxkeysegs;	! OFFSET TO KEY SEGMENTS

!+
!    FLAG BITS DEFINED IN THE KDB
!-
!+
!    *NOTE* THE FLAG FIELD CONTAINS BOTH XAB FLAGS AND
!    TEMPORARY PROCESSING FLAGS. THUS, THE DEFINITIONS OF
!    THE FLAG BITS SHOULD BE SYNCHRONIZED. THAT IS, WHEN NEW
!    PROCESSING FLAGS ARE ADDED, THEY SHOULD BE DEFINED
!    FROM THE LEFT-MOST AVAILABLE BIT IN THE FIELD. USER
!    FLAGS SHOULD BE DEFINED FROM THE RIGHT-MOST AVAILABLE
!    BIT IN THE WORD
!-

LITERAL
    flgnoindex = bitn (18),			! START FLAGS FROM LEFT
    flgdidchange = bitn (19);			! KEY CHANGED DURING UPDATE

!+
!    MACROS USED TO ACCESS KDB FLAGS
!-

MACRO
    noindexflag =
	(.kdb [kdbflags] AND flgnoindex) %,
    duplicates =
	(chkflag (kdb [kdbflags], flgdup) NEQ 0) %,
    noduplicates =
	NOT duplicates %;

!+
!    MACROS USED TO ACCESS THE KEY-OF-REFERENCE FIELD
!-

MACRO
    primarykey =
	(.kdb [kdbref] EQL refprimary) %,
    secondarykey =
	( NOT primarykey) %;

!+
!
!    ***********************************************************************
!    *			END OF KDB.REQ			      *
!    ***********************************************************************
!
!-
!+
!
!    ******************************************************************
!    *			START OF LOCKS.REQ			   *
!    *								   *
!    *			CONTENTS:				   *
!    *								   *
!    *		1.   ENQ/DEQ SYMBOLS				*
!    *		2.   QUEUEING STRUCTURES FOR ENQ/DEQ		  *
!    *		3.   MACROS FOR LOCKING RECORDS, BUCKETS, ETC.	   *
!    *								   *
!    *******************************************************************
!
!    AUTHOR: S. BLOUNT
!
!
!-
!+
!    THERE ARE SEVERAL DIFFERENT TYPES OF LOGICAL RESOURCES
!    WHICH ARE LOCKED BY RMS-20 DURING THE COURSE OF ITS
!    PROCESSING. THE FOLLOWING TYPES OF LOCKS ARE DEFINED
!    WITHIN RMS-20:
!
!    1.	FILE LOCKS WHEN THE FILE IS OPENED.
!    2.	RECORD LOCKS FOR SEQUENTIAL OR RELATIVE FILES
!    3.	BUCKET LOCKS FOR INDEXED FILES.
!    4.	CAPABILITY LOCKS FOR INDEXED FILES.
!
!    ALL OF THESE LOGICAL RESOURCES CONFORM TO THE SAME FORMAT
!    OF LOCK NAMES. THIS MECHANISM INSURES THAT RESOURCE NAMES
!    DO NOT CONFLICT (E.G., A RECORD LOCK DOES NOT HAVE THE SAME
!    FORMAT AS A FILE LOCK, ETC. ). EACH RESOURCE NAME IS IN
!    THE FOLLOWING FORMAT:
!
!    !-------------------------------------!
!    ! 5   !LOCK !          LOCK           !
!    !     !TYPE !       IDENTIFIER        !
!    !-------------------------------------!
!
!    THE "5" IS REQUIRED BY ENQ/DEQ. THE LOCK-TYPE IS 3 BITS
!    AND REPRESENTS THE GENERIC TYPE (FILE, RECORD, BUCKET, CAPABILITY)
!    OF THIS LOCK. THE "LOCK IDENTIFIER" IS THE ACTUAL RESOURCE
!    NAME (E.G, RECORD ID, BUCKET NUMBER, ETC. ). CARE MUST BE
!    USED IN THE CHOICE OF BOTH LOCK TYPE-CODES AND IDENTIFIERS
!    TO INSURE THAT A FUTURE CONFLICT DOES NOT ARISE.
!
!
!-
!+
!
!    ***********************************************************************
!    *			INTERNAL RMS-20 QUEUEING STRUCTURES	      *
!    ***********************************************************************
!
!-
!+
!    ***NOTE THAT IF A NEW BIT IS ADDED TO THIS LIST,
!    ALL FLAG DEFINITIONS MUST BE SHIFTED LEFT 1 BIT,
!    (E.G., #4 BECOMES #10, ETC...)
!-

LITERAL
    enqcall = 1,				!FLAG TO CONTROL ENQ OR DEQ
    deqcall = 0;

!+
!    ENQ JSYS
!-

LITERAL
    enqblk = 0,					! BLOCK FOR RESOURCE
    enqaa = 1,					! ALLOCATE IF AVAILABLE
    enapsi = 2;					! WAIT FOR PSI

!+
!    DEQ JSYS
!-

LITERAL
    deqdr = 0,
    deqda = 1,					! DEQ ALL RESOURCES
    deqid = 2;					! DEQ BY REQUEST ID

LITERAL
    enqshr = %O'10',				! SHARABLE RESOURCE
    enqexc = %O'0',				! EXCLUSIVE ACCESS RESOURCE
    enqbln = %O'4',				! BYPASS LEVEL NUMBERS
%IF %SWITCHES(TOPS20)
%THEN
    enqnst = %O'2',				! ALLOW NESTING (NOT USED)
    enqltl = %O'1';				! LONG TERM LOCK
%ELSE
    enqnst = %O'0',				! ALLOW NESTING (NOT USED)
    enqltl = %O'2';				! LONG TERM LOCK
%FI

!+
!    STRUCTURE OF ENQ/DEQ PARAMETER BLOCK
!-

LITERAL

%IF %SWITCHES(TOPS20)                                                    !m572
%THEN
    qblkntrysz = 3,				! SIZE OF AN ENQ ENTRY
%ELSE
    qblkntrysz = 5,				! SIZE OF AN ENQ ENTRY
%FI
    qblkhdrsz = 2;				! SIZE OF HEADER IN ENQ BLOCK

MACRO
    qhdrcount =
	0, lh %,				! COUNT OF LOCKS
    qhdrlength =
	0, rh %,				! LENGTH OF RESOURCE BLOCK
    qhdrpsi =
	1, lh %,				! PSI CHANNEL
    qhdrid =
	1, rh %,				! REQUEST ID
    qblkflags =
	0, 32, 4, 0 %,				! FLAGS IN LOCK BLOCK
    qblklevel =
	0, 18, 15, 0 %,				! LEVEL NUMBER
    qblkjfn =
	0, rh %,				! JFN
    qblkcode =
	1, wrd %,				! USER CODE
    qblkpool =
	2, lh %,				! POOLED COUNT
    qblkgroup =
	2, rh %,				! SHARER'S GROUP
    qblkword3 =
	2, wrd %;				! ENTIRE 3RD WORD OF BLOCK

!+
!    STRUCTURE OF ENQ/DEQ BLOCK FOR Q'ING FILES
!-

LITERAL
    numflocks = 6,				! NUMBER OF LOCKS FOR FILE
    qblklength = numflocks*qblkntrysz + qblkhdrsz;

!+
!    STRUCTURE OF USER-ID CODE FOR FILE LOCKS
!-

LITERAL
    rmsqcode = %O'500000000000';		! 1ST  DIGIT IS 5 IN FILE LOCKS

!+
!    LOCK-TYPE CODES
!-

LITERAL
    ltyperec = 0,				! THIS IS A RECORD ID
    ltypefile = 1,				! THIS IS A FILE LOCK
    ltypecap = 2,				! THIS IS A CAPABILITY LOCK
    ltypebkt = 3;				! THIS IS A BUCKET LOCK

!+
!    STRUCTURE MACROS FOR USER-ID CODE
!-

MACRO
    qblkltype =
	1, 30, 3, 0 %,				! LOCK-TYPE CODE
    qblklid =
	1, rh %;				! PLACE FOR ID CODE

!+
!    CAPABILITIES
!-

LITERAL
    capindex = 1;				! CAPABILITY OF TRAVERSING THE INDEX

!+
!
!    ***********************************************************************
!    *		MACROS FOR LOCKING AND UNLOCKING FILE RECORDS	      *
!    ***********************************************************************
!
!-
!+
!    MACRO TO UNLOCK A SINGLE RECORD IN A SEQUENTIAL/RELATIVE FILE.
!    NOTE THAT THIS MACRO AUTOMATICALLY SETS THE "DATALOCKED"
!    BIT IN THE RST AFTER THE RECORD HAS BEEN LOCKED.
!-

MACRO
    unlock (recordid) =
	BEGIN

	LOCAL
	    temp;

	IF (temp = .recordid) NEQ 0		! If there is a currently
	    					! locked record
	THEN
	    BEGIN				! TO UNLOCK RECORD

	    IF lockit (deqcall, 		! DEQ
		    deqdr, 			! Function
		    .temp, 			! Record ID
		    0, 				! Access
		    ltyperec)			! LOCK TYPE
		EQL false
	    THEN
		BEGIN
		fileproblem (fe$unl);
		usrerr ();
		END;

	    rst [rstflags] = .rst [rstflags] AND ( NOT flgdlock);
	    END

	END
    %,						! Of UNLOCK macro
!
    !	Macro to lock a single record
    !
    lockrec (recordid) = 			! LOCK A RECORD
	BEGIN

	LOCAL
	    temp,
	    temp2;

	IF inputmode				! Set access
	THEN
	    temp2 = enqshr			! Sharable
	ELSE
	    temp2 = enqexc;			! Exclusive

	IF lockit (enqcall, 			! ENQCALL
		enqaa, 				! Function
		.recordid, 			! Record ID
		.temp2, 			! Access
		ltyperec) EQL false
	THEN
	    usererror (er$rlk);

	setflag (rst [rstflags], flgdlock);	! Remember it's locked
	END
    %;						! Of LOCK macro

!+
!
!    ***********************************************************************
!    *		MACROS FOR LOCKING AND UNLOCKING THE INDEX	     	*
!    ***********************************************************************
!
!-
!+
!   These macros are used to lock/unlock the index
!   structure of an indexed file.  Whenever the index
!   is to be traversed, or any data moved with the
!   file, the index structure must be locked for the
!   duration of the operation.
!-

MACRO
    lockindex (func, acc) =
	BEGIN

	LOCAL
	    xf,
	    xa;					! Some locals to hold args

	xf = func;				! Pick up arguments
	xa = acc + enqltl;			! Get access and set
						!   "long-term lock"

	IF lockit (enqcall, 			! ENQCALL
		.xf, 				! Function
		capindex, 			! ID
		.xa, 				! Access
		ltypecap)			! Index capability
	    NEQ false
	THEN
	    BEGIN				! Set the FST flag bit to
	    					!   denote index is locked
	    setflag (fst [fstflags], flgilocked);
	    true				! Value true
	    END
	ELSE
	    false				! Value false
	END

    %;

!+
!   Macro to unlock the index structure of an indexed file
!-

MACRO
    unlockindex =
	BEGIN
	clrflag (fst [fstflags], flgilocked);	! Clear flag bit
	lockit (deqcall, 			! DEQ it
	    deqdr, 				! Function
	    capindex, 				! ID
	    0, 					! Access
	    ltypecap)				! Index capability
	END
    %;

!+
!
!    ***********************************************************************
!    *		MACROS FOR LOCKING AND UNLOCKING BUCKETS	 *
!    ***********************************************************************
!
!-
!+
!    MACRO TO LOCK A SINGLE BUCKET (I.E., A FILE PAGE NUMBER )
!-

MACRO
    lockbucket (acc, pnum) =
	BEGIN

	LOCAL
	    xacc,
	    xpnum;				! Define locals to pass args in

	xacc = acc;				! Get args in locals
	xpnum = pnum;
	lockit (enqcall, 			! ENQ this bucket
	    enqaa, 				! Function
	    .xpnum, 				! Page number
	    .xacc, 				! ENQ access needed
	    ltypebkt)				! Type of lock (bucket)
	END
    %;

!+
!   Macro to unlock a file bucket for indexed files
!-

MACRO
    unlockbucket (pnum) =
	BEGIN

	LOCAL
	    xpnum;

	xpnum = pnum;
	lockit (deqcall, 			! Make this a DEQ
	    deqdr, 				! Function
	    .xpnum, 				! ID
	    0, 					! No access needed
	    ltypebkt)				! Type of lock
	END
    %;

!+
!
!    ***********************************************************************
!    *		MACROS FOR LOCKING AND UNLOCKING BUCKET DESCRIPTORS  *
!    ***********************************************************************
!
!-
!+
!    MACRO TO LOCK A BUCKET DESCRIPTOR. THIS MACRO WILL
!    LOCK THE BUCKET INDICATED BY THE BUCKET DESCRIPTOR,
!    AND IF SUCCESSFUL, IT WILL SET THE BIT IN THE
!    DESCRIPTOR WHICH INDICATES THAT THE BUCKET IS LOCKED.
!-

MACRO
    lockbd (bd, func, acc) =
	BEGIN

	LOCAL
	    bnum,
	    localfunc,
	    localacc;

	bnum = .bd [bkdbktno];			! GET BUCKET NUMBER
	localfunc = func;
	localacc = acc;


        IF bktlocked (bd)                       !A412 Is bucket already locked?
        THEN true                               !A412 Yes. we can't lose
        ELSE                                    !A412 No. try to lock it
            BEGIN                               !A412
            IF lockit (enqcall,                 ! ENQ call
                    .localfunc,                 ! Function
                    .bnum,                      ! ID
                    .localacc, 			! Access
                    ltypebkt)			! Bucket lock
                NEQ false
            THEN
                BEGIN				! Remember bucket is locked
                setbktlocked (bd);
                true				! Return value true
                END
            ELSE
                false
            END                                 !A412
	END
    %;

!+
!    ****************** END OF LOCKS.REQ REQUIRE FILE**************
!    ****************************************************************
!-
!+
!
!    *****************************************************************
!    *			START OF OS.REQ				*
!    *			CONTENTS:				*
!    *	1.	JSYS & UUO STUFF FOR WHICH RMS USES COMMON SYMS	*
!    *			(EXCEPT ENQ/DEQ -- SEE LOCKS)		*
!    *	2.	MISCEL MONITOR DEPENDENT STUFF			*
!    *****************************************************************
!
!-
! MACRO TO PUT SHORT OS DEP CODE SEQS IN A PROG
!

MACRO
    if$10 (code$) =

	%IF TOPS10
	%THEN
	    code$
	%FI

    %;

MACRO
    if$20 (code$) =

	%IF TOPS20
	%THEN
	    code$
	%FI

    %;

!+
!
!    ***********************************************************************
!    *		TOPS-20/RMS-20 ERROR CODE MAPPING DEFINITIONS	     	*
!    ***********************************************************************
!
!-
!+
!    FIELD DEFINITION MACROS FOR EACH ENTRY IN ERROR MAP TABLE
!-

LITERAL
    sizeofemtentry = 1;				! EACH ENTRY IS TWO WORDS

MACRO
    emtsyscode =
	rh %,					! SYSTEM CODE
    emtrmscode =
	lh %;					! RMS-20 CODE

!+
!    MACRO TO PERFORM MAPPING (CALLS ROUTINE TO DO MAPPING)
!-

MACRO
    mapsystemcode (src, defcode, tabnam) =
	BEGIN
	mapcodes (.src, 			! Sys code
	    defcode, 				! Def code
	    tabnam);				! Table
	END
    %;

! MAP MONITOR STATUS CODES TO RMS STATUS CODES (BUILD MAPPING TABLE)
!
!	BIND table-name = UPLIT(
!			1 or more OSERRMAPs
!			OPSERRMEND;
!

MACRO
    oserrmap (rmerr$) [oserr$] =
	rmerr$^18 OR oserr$ %;

MACRO
    oserrmend =
	0 %;

!+
!   Map monitor status codes to RMS status codes
!
!   BIND
!	table_name = $oserrmap (
!		    <rmscode, oscode [, oscode...]>,
!		    <rmscode, oscode....>);
!-

MACRO
    os$$errmap (rmscode) [oscode] =
	rmscode^18 OR oscode %,
    os$$errmap_intermac [maprelation] =
	os$$errmap (%REMOVE (maprelation)) %,
    $oserrmap (relation) =
	UPLIT (os$$errmap_intermac (relation, %REMAINING), 0) %;

!+
!
!    ***********************************************************************
!    *		COMMON JSYS/UUO SYMBOL  DEFINITIONS		      *
!    ***********************************************************************
!
!-

LITERAL
    opfbszlsh = 30;				!??? FOR NOW

!+
!    FILE DATES
!-

LITERAL
    dates_blksiz = 4,				!SIZE OF BLK RET BY DATOFILE
    dt_wri = 0,					!OFFSET WHERE LAST WRIT DATE IS
    dt_cre = 1;					!OFFSET CREATE DATE

!+
!    DEVCHR JSYS BITS
!-

LITERAL
    dvout = bitn (0),				! DVICE CAN DO OUTPUT
    dvin = bitn (1),				! INPUT
    dvdir = bitn (2),				! DIRECTORY DEVICE (DASD)
    devasn = bitn (3);				! ASSIGNABLE

MACRO
    devtype =
	0, 18, 9, 0 %;				! DEVICE-TYPE FIELD

LITERAL
    dvdsk = 0,					! DEVICE-TYPE CODES...
    dvmta = 2,					! MAGTAPE
    dvlpt = 7,					! LPT
    dvcdr = %O'10',				! CARD-READER

%IF %SWITCHES(TOPS20)
%THEN
    dvtty = %O'12';				! TERMINAL
%ELSE		! TOPS-10

    dvtty = %O'3';				! TERMINAL

MACRO
    dv_typ = %O'77' %;				! TY.DEV from UUOSYM

LITERAL						! GTJFN Unused by TOPS-10
    Gj_New = 0,
    Gj_Old = 0,
    Gj_Fou = 0,
    Gj_Flg = 0,
    Gj_Ofg = 0,
    Gj_Ifg = 0,
    $Erbas = 0;
%FI

!+
!    GTFDB JSYS OFFSETS
!-

LITERAL
    fdbctl = 1,					! CONTROL BITS
    fdbbyv = %O'11',				! BYTE SIZE
    fdbsiz = %O'12';				! EOF BYTE NUMBER

!+
!    BIT DEFINITIONS FOR GTFDB JSYS
!-

LITERAL
    fdbnxf = bitn (4);				! NON-EXISTENT FILE

!+
!    FILE CLASS DEFINITIONS
!-

MACRO
    fdbcls =
	0, 18, 4 %;				! FIELD WHICH DEFINES FILE CLASS

LITERAL
    fdbclsmask = %O'17000000';			! MASK FOR FILE CLASS FIELD

LITERAL
    clsasc = 0,					! ASCII FILE
    clsrms = 1;					! RMS-20 FILE

!+
!    SYMBOLS FOR THE FBBYV FIELD AND THE BSZ PORTION OF IT
!-

LITERAL
    fdbbszmask = %O'7700000000',		! MASK FOR BSZ FIELD
    fdbbszlsh = 24;				! LSH FOR BSZ FIELD

!+
!
!    ******************************************************************
!    *			START OF RDP.REQ			   *
!    *								   *
!    *			CONTENTS:				   *
!    *								   *
!    *		1. STRUCTURE OF THE RECORD DESCRIPTOR PACKET      	*
!
!    *								   *
!    *******************************************************************
!
!    AUTHOR: S. BLOUNT
!
!
!-
!+
!
!    THIS FILE CONTAINS THE STRUCTURE AND ACCESS MACROS USED
!    FOR THE RECORD DESCRIPTOR PACKET.  THIS PACKET (CALLED
!    THE "RECORD DESCRIPTOR" OR "RD" FOR SHORT) IS USED ONLY
!    DURING PROCESSING OF INDEXED FILES IN RMS-20. IT IS PASSED
!    BETWEEN ROUTINES AND CONTAINS TEMPORARY RESULTS WHICH
!    ARE REQUIRED BY OTHER ROUTINES. NOTE THAT THE RECORD DESCRIPTOR
!    DOESN'T ACTUALL "EXIST" ANYWHERE, IT IS ALLOCATED FROM LOCAL
!    STORAGE WHEN NEEDED, AND IS DEALLOCATED WHEN THE INVOKING
!    ROUTINE IS LEFT.
!
!
!    FORMAT OF THE RECORD DESCRIPTOR
!    ===============================
!
!    !=====================================!
!    !      FLAGS       !      STATUS      !
!    !-------------------------------------!
!    !     USERSIZE     !      COUNT       !
!    !-------------------------------------!
!    !    LASTLEVEL     !      LEVEL       !
!    !-------------------------------------!
!    !               USERPTR               !
!    !-------------------------------------!
!    !             LASTRECPTR              !
!    !-------------------------------------!
!    !                RECPTR               !
!    !-------------------------------------!
!    !                 RFA                 !
!    !-------------------------------------!
!    !                 RRV                 !
!    !-------------------------------------!
!    !      LENGTH      !   SIDRELEMENT    !
!    !=====================================!
!
!
!    FIELDS WITHIN THE RECORD DESCRIPTOR
!    ===================================
!
!
!    FIELD			FUNCTION
!    -----			--------
!
!    FLAGS		PROCESSING FLAGS USED AS INPUT TO EACH ROUTINE
!
!    FLGHORIZOK	"HORIZONTAL SEARCH IS OK".
!    THIS FLAG IS SET ON $FIND/$GET AND CLEARED
!    ON A $PUT OPERATION. IT INDICATES THAT WHEN
!    A HORIZONTAL SEARCH MUST BE DONE (IN THE
!    CASE OF A SYSTEM CRASH DURING AN INDEX UPDATE,
!    FOR EXAMPLE), THE SEARCH SHOULD CONTINUE
!    AT THE TOP OF THE NEXT BUCKET. IF THIS FLAG
!    IS NOT SET, THEN THE SEARCH ALGORITHM WILL
!    POSITION BACK TO THE END OF THE CURRENT
!    BUCKET IF THE SEARCH KEY IS LESS THAN THE FIRST
!    RECORD IN THE NEW BUCKET.
!    FLGRETEX	FLAG SET BY RMSUTL. TELLS CHKDUP TO
!    RETURN IF CALLER'S RRV IS IN SIDR ARRAY.
!    WHEN OFF, CHKDUP 0'S SUCH ENTRIES.
!
!    STATUS		STATUS FLAGS USED AS OUTPUT FROM EACH ROUTINE
!
!    FLGIDXUPDATE		AN INDEX UPDATE IS REQUIRED
!    FLGDUP			A DUPLICATE KEY WAS SEEN
!    FLGEMPTY		CURRENT BUCKET IS EMPTY
!    FLGLSS			CURRENT SEARCH KEY IS LSS TARGET KEY
!    FLGDELETE		CURRENT RECORD IS DELETED
!    FLGIDXERROR		AN INDEX ERROR WAS DETECTED
!    FLGNOHIKEY		THERE IS NO NEW HI-KEY FOR A BUCKET
!    DURING A SPLIT (CAUSED BY BUCKET FILLED
!    WITH RRV'S ETC. )
!
!    USERSIZE	SIZE OF USER SEARCH KEY IN BYTES
!
!    COUNT		MISCELLANEOUS COUNTER VALUES.
!    USED BY SPLIT TO DENOTE THE NUMBER OF BUCKETS
!    WHICH WERE REQUIRED FOR THE SPLIT.
!
!    LASTLEVEL	THE LEVEL AT WHICH A SEARCH TERMINATED
!
!    LEVEL		THE LEVEL AT WHICH THE SEARCH SHOULD TERMINATE (INPUT)
!
!    USERPTR		ADDRESS OF USER SEARCH KEY
!
!    LASTRECPTR	ADDRESS OF RECORD BEFORE THE ONE WHICH TERMINATED
!    THE CURRENT SEARCH.
!
!    RECPTR		ADDRESS OF CURRENT RECORD IN BUCKET
!
!    RFA		ADDRESS (RFA FORMAT) OF TARGET RECORD.
!
!    RRV		ADDRESS (RRV FORMAT) OF CURRENT RECORD
!
!    LENGTH		MISCELLANEOUS LENGTH VALUES.
!
!    SIDRELEMENT	OFFSET INTO CURRENT SIDR ARRAY OF THE TARGET
!    RECORD POINTER (1 MEANS FIRST POINTER, ETC. ).
!    THIS FIELD IS SAME IN MEANING AS RSTSIDRELEMENT,
!    BUT IS PASSED IN THE RDP BECAUSE THE RST IS NOT
!    UPDATED ON EVERY OPERATION.
!
!    RPSIDR		TENTATIVE SIDRELEMENT AFTER $FIND
!
!
!-
!+
!
!    *****************************************************************
!    *		RECORD DESCRIPTOR PACKET DEFINITIONS		*
!    *****************************************************************
!
!-
!+
!    THE RECORD DESCRIPTOR PACKET IS A LOCAL ARGUMENT
!    BLOCK WHICH IS USED TO PASS A SERIES OF ARGUMENTS
!    BETWEEN ROUTINES FOR PROCESSING INDEXED FILES. THESE
!    PARAMETERS ARE NOT PLACED IN THE RST TO CONSERVE SPACE
!    AND BECAUSE THE CONTENTS OF THE PACKET MAY NOT BE
!    INVARIENT ACROSS ROUTINE CALLS.
!-

%IF indx
%THEN

LITERAL
    rdsize = 9;					! SIZE OF IT

MACRO
    rdflags =
	0, lh %,				! PROCESSING FLAGS
    rdstatus =
	0, rh %,				! STATUS
    rdusersize =
	1, lh %,				! SIZE OF RECORD/KEY
    rdcount =
	1, rh %,				! COUNT FIELD
    rdlastlevel =
	2, lh %,				! LAST LEVEL PROCESSED
    rdlevel =
	2, rh %,				! INPUT LEVEL NUMBER
    rduserptr =
	3, wrd %,				! ADDR OF USER RECORD/KEY
    rdlastrecptr =
	4, wrd %,				! LAST RECORD IN BKT
    rdrecptr =
	5, wrd %,				! ADDRESS OF RMS RECORD
    rdrfa =
	6, wrd %,				! RECORD RFA
    rdrrv =
	7, wrd %,				! RECORD RRV ADDRESS
    rdlength =
	8, lh %,				! LENGTH OF RECORD TO INSERT
    rdsidrelement =
	8, rh %;				! OFFSET OF CURRENT RECORD POINTER

!+
!
!    ***********************************************************************
!    *		RECORD DESCRIPTOR FLAGS AND MACROS TO USE THEM	     *
!    ***********************************************************************
!
!-
!+
!    RECORD DESCRIPTOR FLAG BIT DEFINITIONS
!-

LITERAL
    rdflgssk = bitn (35),			! SEGMENTED SEARCH KEY
    rdflgretex = bitn (34),			!TELLS CHKDUP TO RET IMMED
    rdflghorizok = bitn (33);			! A HORIZONTAL SEARCH IS OK

! RETRY IF BUSY
!+
!    RECORD DESCRIPTOR STATUS BIT DEFINITIONS
!-

LITERAL
    rdflgidxupdate = bitn (35),			! INDEX UPDATE REQUIRED
    rdflgdup = bitn (34) :,			! KEY ALR IN BKT (SEE FLGSAME)
    rdflgempty = bitn (33) :,			! BUCKET IS EMPTY
    rdflgpst = bitn (32) :,			! SEARCH WENT PAST LAST RECORD IN BKT
    rdflglss = bitn (31) :,			! SEARCH KEY IS LESS
    rdflgdelete = bitn (30) :,			! RECORD IS DELETED
    rdflgidxerror = bitn (29) :,		! INDEX UPDATE ERROR OCCURED
    rdflgnohikey = bitn (28) :,			! NO HI-KEY IN OLD BKT (FOR SPLIT)
    rdflgnewinnew = bitn (27),			! SEQ ACC, 2-WAY SPLIT & R-NEW IN NEW BUCKET
    rdflgsame = bitn (26);			! OTHER EXISTING REC HAS A KEY SAME AS A KEY OF NEW REC

!+
!    MACRO WHICH REFER TO THESE FLAGS AND STATUS BITS
!-

MACRO
    sskflag (rdptr) =
	(.rdptr [rdflags] AND rdflgssk) %,
    retryflag (rdptr) =
	(.rdptr [rdflags] AND rdflgretry) %,
    horizokflag (rdptr) =
	(.rdptr [rdflags] AND rdflghorizok) %,
    emptyflag (rdptr) =
	(.rdptr [rdstatus] AND rdflgempty) %,
    idxerrorflag (rdptr) =
	(.rdptr [rdstatus] AND rdflgidxerror) %,
    idxupdateflag (rdptr) =
	(.rdptr [rdstatus] AND rdflgidxupdate) %,
    lssflag (rdptr) =
	(.rdptr [rdstatus] AND rdflglss) %,
    pastlastflag (rdptr) =
	(.rdptr [rdstatus] AND rdflgpst) %,
    duplicateflag (rdptr) =
	(.rdptr [rdstatus] AND rdflgdup) %,
    samekeyflag (rdptr) =
	(.rdptr [rdstatus] AND rdflgsame) %,
    flushorigbd (rdptr) =
	(.rdptr [rdstatus] AND rdflgnewinnew) %;

!+
!    MACROS TO SET OR CLEAR THESE FLAGS
!-

MACRO
    setemptyflag (rdptr) =
	setflag (rdptr [rdstatus], rdflgempty) %,
    setretryflag (rdptr) =
	setflag (rdptr [rdflags], rdflgretry) %,
    setlssflag (rdptr) =
	setflag (rdptr [rdstatus], rdflglss) %,
    setpastlastflag (rdptr) =
	setflag (rdptr [rdstatus], rdflgpst) %,
    setduplicatflag (rdptr) =
	setflag (rdptr [rdstatus], rdflgdup) %,
    setsamekeyflag (rdptr) =
	setflag (rdptr [rdstatus], rdflgsame) %,
    setidxupdatflag (rdptr) =
	setflag (rdptr [rdstatus], rdflgidxupdate) %,
    setidxerrorflag (rdptr) =
	setflag (rdptr [rdstatus], rdflgidxerror) %,
    setnewinnewflg (rdptr) =
	setflag (rdptr [rdstatus], rdflgnewinnew) %;

!+
!    MACRO TO DUMP OUT THE CONTENTS OF THE RECORD DESCRIPTOR.
!    NOTE THAT THE SECOND ARGUMENT TO THIS MACRO MUST BE A
!    BASE PARAMETER.
!-

MACRO
    dumptherd (text, rdadr) =

	%IF dbug
	%THEN
	    begindebug (dblocal)		!
	    type(text);				!
	    dumprd (bpt (rdadr));		!
	    enddebug				!
	%FI

    %;

%FI

!+
!
!    ***********************************************************************
!    *			END OF RDP.REQ			      *
!    ***********************************************************************
!
!-
!+
!
!    ******************************************************************
!    *			START OF RST.BLI			   *
!    *								   *
!    *			CONTENTS:				   *
!    *								   *
!    *		1..	STRUCTURES FOR RECORD STATUS TABLE	   *
!    *								   *
!    *******************************************************************
!
!    AUTHOR: S. BLOUNT
!
!-
!+
!    THE RECORD STATUS TABLE (RST) IS THE INTERNAL
!    DATA STRUCTURE WHICH REPRESENTS ALL CURRENT INFORMATION,
!    BOTH STATIC AND DYNAMIC, CONCERNING THE STATE OF
!    THE CORRESPONDING RECORD STREAM. THERE IS EXACTLY ONE
!    RST FOR EACH RECORD STREAM WHICH IS CONNECTED TO A
!    PARTICULAR FILE. AN RST IS ALLOCATED WHEN A $CONNECT
!    IS ISSUED AND DE-ALLOCATED WHEN A $DISCONNECT (OR $CLOSE)
!    IS ISSUED.
!
!    IN THE DESIGN OF THE STRUCTURE OF THE RST, THE ISSUE OF
!    ACCESS PERFORMANCE WAS AFFORDED A HIGHER PRIORITY THAN
!    THAT OF INTERNAL BLOCK SIZE. THEREFORE, THERE ARE SEVERAL
!    FIELDS (EXPLAINED BELOW) WHICH ARE NOT ABSOLUTELY NECESSARY
!    FOR THE CORRECT PROCESSING OF THE FILE, BUT WHICH ARE
!    MAINTAINED IN THE RST BECAUSE THEY SERVE TO SPEED UP
!    CERTAIN OPERATIONS ON THE FILE.
!
!    THE FORMAT OF THE RST IS AS FOLLOWS:
!
!
!    !=====================================!
!    !       BID        !       BLN        !
!    !-------------------------------------!
!    !      BLINK       !      FLINK       !
!    !-------------------------------------!
!    !       FST        !      FLAGS       !
!    !-------------------------------------!
!    !       RSZ        !       RSZW       !
!    !-------------------------------------!
!    !               PAGPTR                !
!    !-------------------------------------!
!    !               DATARFA               !
!    !-------------------------------------!
!    !                 NRP                 !
!    !-------------------------------------!
!    !     KEYBUFF      !BFDCNT.!RH !LOPER !
!    !-------------------------------------!
!    !                CBKD                 !
!    !     (CURRENT BUCKET DESCRIPTOR)     !
!    !                                     !
!    !-------------------------------------!
!    !              HYBYTE                 !
!    !-------------------------------------!
!    ! RPREF  ! NRPREF  !    BYTECOUNT     !
!    !-------------------------------------!
!    !               NRPRRV                !
!    !-------------------------------------!
!    !     RPSIDR       !   SIDRELEMENT    !
!    !-------------------------------------!
!    !           BUFFER DESC. #1           !
!    !-------------------------------------!
!    !                  .                  !
!    !                  .                  !
!    !-------------------------------------!
!    !           BUFFER DESC. #N           !
!    !=====================================!
!
!-
!+
!    FIELDS WITHIN THE RECORD STATUS TABLE
!    =====================================
!
!
!    FIELD		FUNCTION
!    =====		========
!
!    BID		BLOCK ID OF RST
!
!    BLN		LENGTH OF RST
!
!    BLINK		BACK LINK TO LAST RST ON CHAIN
!
!    FLINK		FORWARD LINK TO NEXT RST ON CHAIN
!
!    FST		ADDRESS OF RELATED FST
!
!    FLAGS		PROCESSING FLAGS
!    FLGPARTIAL	THE LAST RECORD WAS A "PARTIAL" RECORD (ASCII/LSA)
!    FLGEOF		THE EOF HAS BEEN REACHED..NO MORE INPUT ALLOWED (STM/LSA)
!    FLGDLOCK	THE CURRENT RECORD (IN DATARFA) IS LOCKED
!    (SEQUENTIAL/RELATIVE ONLY)
!    FLGSUCCESS	LAST OPERATION WAS A SUCCESS
!    FLGUPDPTR	PAGPTR MUST BE UPDATED BEFORE NEXT OPERATION
!    (STM/LSA ONLY)
!    FLGLASTSEQ	LAST OPERATION USED SEQ ACCESS (USED TO CHECK
!    KEYS ON SEQ $PUT TO INDEXED FILE)
!    FLGTRUNC	A $TRUNCATE WAS DONE ON THIS STREAM
!
!    RSZ		SIZE IN BYTES OF CURRENT RECORD (OPTIMIZATION)
!
!    RSZW		SIZE IN WORDS OF CURRENT RECORD ( " )
!
!    PAGPTR		POINTER INTO FILE BUFFER OF CURRENT RECORD.
!    FOR ASCII/LSA FILES, THIS IS A BYTE PTR. FOR
!    SEQ/REL FILES, IT IS A WORD ADDRESS WHICH IS NOT
!    PRESERVED ACROSS USER CALLS. FOR INDEXED FILES,
!    IT POINTS TO HEADER OF CURRENT RECORD.
!
!    DATARFA		RFA OF CURRENT RECORD
!    ASCII/LSA:	BYTE NUMBER OF THE START OF CURRENT RECORD
!    SEQ/REL:	RFA OF CURRENT RECORD/0
!    INDEXED:	RFA OF DATA RECORD (NOT RRV)
!
!    NRP		NEXT RECORD POINTER.
!    ASCII/LSA:	BKT# OF NEXT I/O FOR ASCII RECORDS
!    SEQ/REL:	RFA OF NEXT RECORD
!    INDEXED:	RFA OF DATA RECORD (NOT RRV) OF  THE
!    LAST RECORD WHICH CHANGED THE NRP.
!    (FOR PRIMARY KEYS, THIS IS THE UDR RFA,
!    FOR SECONDARY KEYS, IT'S THE SIDR RFA)
!
!    KEYBUFF		ADDRESS OF KEY BUFFER FOR INDEXED FILES
!
!    BFDCOUNT	NUMBER OF BUFFERS ALLOCATED TO THIS STREAM
!
!    RHSIZE		SIZE OF RECORD HEADER (STM/LSA).
!    USED TO COMPUTE WHERE NEXT RECORD BEGINS.
!
!    LASTOPER	OPERATION CODE OF LAST SUCCESSFUL OPERATION
!
!    CBKD		CURRENT BUCKET DESCRIPTOR
!
!    RPREF		KEY OF REFERENCE OF CURRENT RECORD (INDEXED)
!
!    NRPREF		KEY OF REFERENCE OF NEXT RECORD POINTER
!
!    NRPRRV		ADDRESS (RRV FORMAT) OF NEXT RECORD
!
!    SIDRLELEMENT	OFFSET INTO CURRENT SIDR SEGMENT (POINTER ARRAY)
!    OF CURRENT RECORD POINTER (1 MEANS FIRST POINTER, ETC.)
!
!    BUFFER DESC'S	BUFFER DESCRIPTORS FOR THIS STREAM
!
!
!-
!+
!    RECORD STATUS TABLE (RST) STRUCTURE MACROS
!    ==========================================
!-

LITERAL
    rstcode = 4,				! BLOCK-TYPE FOR RST
    rstsize = 15;				! LENGTH OF FIXED PORTION OF AN RST

MACRO 						!BLOCKTYPE = 0,LH$,		! BLOCK-TYPE CODE
    !BLOCKLENGTH = 0,RH$,		! LENGTH OF RST
    !BLINK = 1,LH$,			! BACK LINK TO LAST BLOCK ON CHAIN
    !FLINK = 1,RH$,			! FORWARD LINK ON CHAIN
    rstfst =
	2, lh %,				! POINTER TO FILE FST
    rstflags =
	2, rh %,				! PROCESSING FLAGS
    rstrsz =
	3, lh %,				! SIZE OF CURRENT RECORD IN BYTES
    rstrszw =
	3, rh %,				! SIZE OF RECORD IN WORDS
    rstpagptr =
	4, wrd %,				! POINTER TO CURRENT RECORD
    rstdatarfa =
	5, wrd %,				! RFA OF LAST RECORD ACCESSED
    rstnrp =
	6, wrd %,				! NEXT RECORD POINTER
    rstkeybuff =
	7, lh %,				! ADDRESS OF KEY BUFFER
    rstbfdcount =
	7, 10, 8, 0 %,				! COUNT OF BUFFER DESCRIPTORS
    rstrhsize =
	7, 6, 4, 0 %,				! SIZE OF RECORD HEADER FOR STREAM FILE
    rstlastoper =
	7, 0, 6, 0 %,				! LAST OPERATION ON THIS RST
    rstcbkd1 =
	rstcbdoffset, wrd %,			! CURRENT BUCKET DESCRIPTOR
    rstcbkd2 =
	rstcbdoffset + 1, wrd %,		! REST OF CURRENT BKT DESC.
    rsthybyte =
	10, wrd %,				! HIGHEST BYTE WRITTEN INTO
    rstrpref =
	11, 27, 9, 0 %,				! KEY OF REFER. FOR RP
    rstnrpref =
	11, 18, 9, 0 %,				! KEY OF REFER. FOR NRP
    rstbytecount =
	11, rh %,				! FOR STM AND LSA:  NO. CHARS LEFT ON PAGE
    rstnrprrv =
	12, wrd %,				! RRV ADDRESS OF NRP (INDEXED)
    rstrpsidr =
	13, lh %,				! TENTATIVE SIDR ELEM AFT $FIND
    rstsidrelement =
	13, rh %,				! OFFSET OF CURRENT RECORD POINTER
    rstbfd =
	14, wrd %;				! FIRST BUFFER DESCRIPTOR

!RSTLRU = 14+NUMBUF,WRD		! LRU VECTOR FOLLOWS BFD VECTOR
!+
!    FLAGS USED IN RST FLAG WORD
!-

LITERAL
    flgpartial = bitn (35),			! PARTIAL RECORD
    flgeof = bitn (34),				! EOF ON THIS BUFFER
    flgdlock = bitn (33),			! CURRENT RECORD ( DATARFA ) IS LOCKED
    flgsuccess = bitn (32),			! LAST OPERATION WAS A SUCCESS
    flgupdptr = bitn (30),			! PAGPTR MUST BE UPDATED
    						! ON NEXT OPER. (ASCII ONLY)
    flglastseq = bitn (29),			! LAST OPERATION WAS SEQUENTIAL
    flgtrunc = bitn (28);			! A $TRUNCATE WAS DONE

!+
!    MACROS FOR ACCESSING RST FLAG BITS
!-

MACRO
    datalocked =
	(.rst [rstflags] AND flgdlock) NEQ 0 %,	! DATA RECORD IS LOCKED
    datanotlocked =
	NOT datalocked %,
    clearlockedbit =
	clrflag (rst [rstflags], flgdlock) %,
    setrplocked =
	setflag (rst [rstflags], flgdlock) %;

!+
!    MACRO FOR CHECKING END-OF-FILE FLAG
!-

MACRO
    endoffile =
	(.rst [rstflags] AND flgeof) NEQ 0 %;

!+
!    MACROS FOR CHECKING RST FLAGS
!-

MACRO
    partialflag =
	(.rst [rstflags] AND flgpartial) %,
    eofflag =
	(.rst [rstflags] AND flgeof) %;

!+
!    STREAM FILE RECORD HEADER SIZE DEFINITIONS
!-

LITERAL
    stmrhasc = 0,				! NO RECORD HEADER FOR ASCII STREAM FILES
    stmrhlsn = 5 + 1,				! LSN FOR LSA FILE
    stmrhpm = 5;				! PAGEMARK FOR LSA FILE

!+
!    MACROS FOR ACCESSING THE "SUCCESS" FLAG
!-

MACRO
    success =
	(.rst [rstflags] AND flgsuccess) NEQ 0 %,	! THERE WAS SUCCESS
    clearsuccess =
	rst [rstflags] = (.rst [rstflags] AND ( NOT flgsuccess)) %,
    setsuccess =
	BEGIN
	rst [rstflags] = .rst [rstflags] OR flgsuccess;
	rst [rstlastoper] = currentjsys;
	END
    %;

!+
!
!    *****************************************************************
!    *		"CURRENT" BUCKET DESCRIPTOR DEFINITIONS		*
!    *****************************************************************
!
!-
!+
!    OFFSET INTO THE RST FOR THE CURRENT BUCKET DESCRIPTOR
!-

LITERAL
    rstcbdoffset = 8;				! OFFSET INTO RST

!+
!    MACROS TO SET OR RELEASE THE CURRENT BUCKET FOR INDEXED FILES
!-

MACRO
    setcurrentbkt (bktdesc) =
	BEGIN
	movebktdesc (bktdesc, 			! From
	    cbd);				! To
	END
    %;

MACRO
    fetchcurrentbkt (bktdesc) =
	movebktdesc (cbd, 			! From
	    bktdesc) %;				! To

MACRO
    releascurentbkt =
	BEGIN

	IF NOT nullbd (cbd)
	THEN 					! Release the bucket
	    putbkt (false, 			! No update
		.cbd);				! This bucket

	setnullbd (cbd);			! Flag as empty
	END
    %;

!+
!    MACROS FOR ACCESSING FIELDS IN THE CURRENT BUCKET DESCRIPTOR
!-

MACRO
    currentwindow =
	cbd [bkdbktadr]^w2p %,			! CURRENT WINDOW
    currentfilepage =
	cbd [bkdbktno] %,			! FILE PAGE IN WINDOW
    curentbufferadr =
	cbd [bkdbktadr] %;			! ADDR OF BUFFER

!+
!    ****************	END OF RST.REQ	*****************
!-
!+
!
!    ******************************************************************
!    *			START OF STATUS.REQ			   *
!    *								   *
!    *			CONTENTS:				   *
!    *								   *
!    *		1. RMS-20 STATUS BIT DEFINITIONS   		   *
!    *								   *
!    *******************************************************************
!
!    AUTHOR: S. BLOUNT
!
!
!-
!+
!
!    ***********************************************************************
!    *			STATUS BIT DEFINITIONS			*
!    ***********************************************************************
!
!-
!+
!    EACH OF THE FOLLOWING BITS IS CONTAINED WITHIN "RMSSTS"
!-

LITERAL
    stsnomessage = bitn (35);			! DON'T PRINT ERROR MESSAGES

!+
!
!    *****************************************************************
!    *								*
!    *								*
!    *	$UTLINT  INTERFACE - PRIVATE RMS ENTRIES		*
!    *								*
!    *								*
!    *****************************************************************
!
!
!-
!<BLF/NOMACRO>
!<BLF/NOFORMAT>
!<BLF/NOERROR>

MACRO
    $$u_funct (func) =
	LITERAL
	    %NAME ('U$', func) = u$$max		! 
	    %ASSIGN (u$$max, u$$max + 1) %;

!<BLF/MACRO>
!<BLF/FORMAT>
!<BLF/ERROR>

COMPILETIME
    u$$max = 0;

$$u_funct (setenvir);
$$u_funct (gmem);
$$u_funct (gpage);
$$u_funct (pmem);
$$u_funct (ppage);
$$u_funct (unused1);
$$u_funct (chkdup);

LITERAL
    u$envneed = u$chkdup;			!GE THIS NEEDS RST/FST

$$u_funct (ckeyku);
$$u_funct (ckeykk);
$$u_funct (fbyrrv);
$$u_funct (fbyrfa);
$$u_funct (fnddata);
$$u_funct (folopath);
$$u_funct (getbkt);
$$u_funct (getidb);
$$u_funct (getkdb);
$$u_funct (getroot);
$$u_funct (gtbktptr);
$$u_funct (movekey);
$$u_funct (path);
$$u_funct (putbkt);
$$u_funct (putsidr);
$$u_funct (alcbkt);				! Allocate a bucket	!A442
!
!	Definition of the argument list passed to RMSUIN.
!

MACRO
    no_of_args =
	0, lh %,
    rms_func =
	0, rh %,
    arg_1 =
	1, wrd %,
    arg_2 =
	2, wrd %,
    arg_3 =
	3, wrd %,
    arg_4 =
	4, wrd %,
    arg_5 =
	5, wrd %;

! Definition of  a macro to build the argument list to interface with RMS.
!
! arg_lst_ptr:	Must be POINTER Struct if it contains addr of argblk.
!		Must be FORMATS struct if it is addr of argblk.
! function:	Must be one of the U$$  functions.
! a1,...  :	List of arguments

MACRO
    bld_arg_lst (arg_lst_ptr, function) = 	!iterative macro
	BEGIN

	MACRO
	    bld_lst (a1) [] = 			! this is a recursive macro
		arg_lst_ptr [%COUNT + 1, wrd] = a1;	!first argument to the list
		bld_lst (%REMAINING)		!subsequent args
		%QUOTE %;

	arg_lst_ptr [rms_func] = function;
	arg_lst_ptr [no_of_args] = -(%LENGTH - 2);	!because this macro has two extra args
	bld_lst (%REMAINING);
	END
    %;						!END OF MACRO BLD_ARG_LST

!+
!
!    ********************************************************
!    *							*
!    *		START OF XFILES.REQ			*
!    *							*
!    *		CONTENTS:				*
!    *							*
!    *	1. BLOCK-TYPE DEFINITIONS FOR INDEXED FILES	*
!    *	2. AREA DESCRIPTOR STRUCTURES			*
!    *	3. INDEX DESCRIPTOR STRUCTURES			*
!    *	4. MISCELLANEOUS MACROS USED IN CONVERSIONS	*
!    *							*
!    *********************************************************
!
!    AUTHOR: S. BLOUNT
!
!
!-
!+
!
!    ****************************************************************
!    *			BLOCK-TYPE DEFINITIONS			*
!    *****************************************************************
!
!-
!+
!    BLOCK-TYPES FOR RMS-20 INDEXED FILE PROLOGUES
!-

LITERAL
    adbcode = %O'1756',				! AREA DESCRIPTOR BLOCK
    idbcode = %O'1755';				! INDEX DESCRIPTORS

!+
!
!    *****************************************************************
!    *		AREA DESCRIPTOR BLOCK				*
!    *****************************************************************
!
!-
!+
!    FORMAT OF THE AREA DESCRIPTOR BLOCK
!    ===================================
!
!    !=====================================!
!    !       BID        !       BLN        !
!    !-------------------------------------!
!    !         <UNUSED>          !   BKZ   !	AREA #0
!    !-------------------------------------!
!    !              <UNUSED>               !
!    !-------------------------------------!
!    !              <UNUSED>               !
!    !-------------------------------------!
!    !              <UNUSED>               !
!    !-------------------------------------!
!    !              <UNUSED>               !
!    !-------------------------------------!
!    !         <UNUSED>          !   BKZ   !	AREA #1
!    !-------------------------------------!
!    !                  .                  !	  .
!    !                  .                  !	  .
!    !                  .                  !	  .
!    !=====================================!
!
!-
!+
!    STRUCTURE DEFINITIONS FOR AREA DESCRIPTOR
!-

MACRO
    adbbkz =
	0, 9, 0 %;				! BUCKET-SIZE FOR AREA

!+
!    SIZE OF EACH AREA DESCRIPTOR (ALWAYS ONE WORD)
!-

LITERAL
    areadescsize = 5;				! EACH ABD ENTRY

!+
!
!    *****************************************************************
!    *		INDEX DESCRIPTOR BLOCK				*
!    *****************************************************************
!
!-
!+
!    FORMAT OF AN INDEX DESCRIPTOR BLOCK
!    ===================================
!
!    !=====================================!
!    !       BID        !       BLN        !
!    !-------------------------------------!
!    !       ROOT       !     <UNUSED>     !
!    !-------------------------------------!
!    ! LEVELS !            NXT             !
!    !-------------------------------------!
!    !              <UNUSED>               !
!    !-------------------------------------!
!    !              <UNUSED>               !
!    !-------------------------------------!
!    !              <UNUSED>               !
!    !-------------------------------------!
!    !                                     !
!    !                                     !
!    !            COPY OF USER             !
!    !                                     !
!    !               KEY XAB               !
!    !                                     !
!    !                                     !
!    !                                     !
!    !-------------------------------------!
!    !                                     !
!    !                                     !
!    !              KEY NAME               !
!    !              (7 WORDS)              !
!    !                                     !
!    !=====================================!
!
!-
!+
!    DEFINITIONS FOR IDB FIXED-LENGTH HEADER
!-

LITERAL
    idbxaboffset = 6,				! OFFSET TO USER XAB
    idbhdrsize = idbxaboffset,			! SIZE OF HEADER (SAME)
    idbsize = idbhdrsize + keynamesize;		! SIZE OF IDB (MINUS XAB)

!+
!    STRUCTURE DEFINITIONS FOR FIXED HEADER
!-

MACRO 						!BLOCKTYPE	=	0,LH$,		! BLOCK-TYPE
    						!BLOCKLENGTH	=	0,RH$,		! SIZE OF BLOCK
    idbroot =
	1, lh %,				! ROOT BUCKET FOR INDEX
    idbreser1 =
	1, rh %,				! ***<UNUSED>***
    idblevels =
	2, 27, 9, 0 %,				! # OF LEVELS
    idbnxt =
	2, 0, 27, 0 %,				! NEXT IDB IN CHAIN
    idbreser2 =
	3, wrd %,				! ***<UNUSED>***
    idbreser3 =
	4, wrd %,				! ***<UNUSED>***
    idbreser4 =
	5, wrd %;				! ***<UNUSED>***

!+
!
!    ****************************************************************
!    *			MISCELLANEOUS MACROS				*
!    *****************************************************************
!
!-
!+
!    MACRO TO CONVERT AN AREA NUMBER TO A BUCKET SIZE
!-

MACRO
    areatobktsize (areanum) =
	.adb [(areanum*areadescsize) + 1, adbbkz] %;

!+
!
!    ****************************************************************
!    *			END OF XFILES.REQ			*
!    *****************************************************************
!
!-