Google
 

Trailing-Edge - PDP-10 Archives - cuspbinsrc_2of2_bb-fp63b-sb - 10,7/rms10/rmssrc/rmsasc.b36
There are 6 other files named rmsasc.b36 in the archive. Click here to see a list.
MODULE ASCII =


BEGIN

GLOBAL BIND	ASCIV = 1^24 + 0^18 + 8;	!EDIT DATE: 12-Jan-82

%([
FUNCTION:	THIS MODULE CONTAINS ALL ROUTINES WHICH PROCESS
		RECORDS WITH AN ASCII OR LINE-SEQUENCED (LSA) FILE

AUTHOR:	S. BLOUNT

THIS SOFTWARE IS FURNISHED UNDER A LICENSE AND MAY ONLY BE USED
  OR COPIED IN ACCORDANCE WITH THE TERMS OF SUCH LICENSE.

!COPYRIGHT (C) 1977, 1982 BY DIGITAL EQUIPMENT CORPORATION



**********	TABLE OF CONTENTS	**************




	ROUTINE			FUNCTION
	=======			========

	PUTASCII		PROCESS THE $PUT MACRO FOR ASCII/LSA FILES

	PUTLSN			WRITE A LINE-SEQUENCE NUMBER INTO A LSA FILE

	GETASCII		PROCESS THE $GET MACRO FOR ASCII/LSA FILE

	GETLSN			READ A LINE-SEQUENCE NUMBER FROM LSA FILE





REVISION HISTORY:

EDIT	WHO	DATE		PURPOSE
====	===	====		=======

1	JK	5-AUG-76	NEW ASCII CHANGES.
2	JK	17-AUG-76	'USRSTV' SHOULD HAVE PARTIAL RECORD SIZE FOR 'ER$RTB'.
3	SB	3-OCT-76	CLEAN-UP SOME CODE, ADD UPDPTR BIT
4	SB	23-NOV-76	CHANGE ER$REX TO ER$NEF
5	SB	7-FEB-77	SET UPDPTR FLAG WHEN READING PAGE MARK
6	SB	23-FEB-77	FIX GET PAGE MARK TO RETURN CR-FF
7	SB	7-APR-77	CHANGE HYBYTE TO RST

*************************************************
*						*
*		NEW REVISION HISTORY		*
*						*
*************************************************

PRODUCT	MODULE	 SPR
 EDIT	 EDIT	 QAR		DESCRIPTION
======	======	=====		===========

56	8	XXXXX		Don't give ER$UDF-ER$LSA when
				there is a word of nulls right
				before the TOPS-10 block boundary in an
				LSA file. Some editors do this so programs
				can read the linenumber-tab sequence in the
				same buffer. If there are nulls instead
				of a line number in a random place however,
				still give the error.

	***** END OF REVISION HISTORY *****




])%



	%([ EXTERNAL	ROUTINES ])%

EXTERNAL ROUTINE
    DUMP,
    CRASH,
    WRITEBUFFER,
    READBUFFER;

%([ ERROR MESSAGES REFERENCED WITHIN THIS MODULE ])%

EXTERNAL
    MSGMOVESTRING;		! MOVE-STRING FAILED



FORWARD ROUTINE		GETLSN: NOVALUE,
			GETASCII,
			PUTLSN: NOVALUE;









REQUIRE 'RMSREQ';
EXTDECLARATIONS;



	%([ SYMBOLS USED FOR LINE-SEQUENCED FILES: ])%

	LITERAL	PAGEMARKCODE	=	%O'777777',	! LINE-NUMBER FOR PAGE MARK
		PAGEMARKSIZE	=	2*5,		! # OF CHARS IN PAGE-MARK
		PMRECSIZE	=	2,		! SIZE OF DATA IN PAGE MARK
		LINENUMFLAG	=	BITN ( 35 ),	! FLAG TO DENOTE LINE-NUMBER
		LSNBUFSIZE	=	%O'200',	! SIZE OF A TOPS-10 BUFFER	!A56
		PAGEMARK1	=	%ASCII '     ' + LINENUMFLAG,
		PAGEMARK2	=	( ( CHARCR ^ 7 ) + CHARFF ) ^ 22;



! PUTASCII
! ========

! THIS ROUTINE PROCESSES THE $PUT MACRO FOR ASCII AND LINE-SEQUENCED
!	ASCII FILES.  IT IS PLACED IN THIS MODULE IN ORDER TO
!	LOCALIZE ALL ACCESS TO NON-RMS FILE ORGANIZATIONS.

! INPUT:
!	<NONE>

! OUTPUT:
!	<NONE>

! GLOBALS USED:
!	<NONE>

! NOTES:
!
!	1.	THE FOLLOWING SYMBOLS ARE MACROS WHICH ARE DEFINED
!		IN "RST.REQ". DO NOT CONFUSE THEM WITH LOCAL VARIABLES:
!
!			CURRENTBUFFERADR

GLOBAL ROUTINE PUTASCII: NOVALUE  =
BEGIN

LOCAL
    TEMP1,
    TEMP2,
    TEMP3,
    TEMP4,
    FILEPOINTER,		! PTR TO THE FILE BUFFER
    USERPOINTER,		! PTR TO THE USER'S RECORD BUFFER
    DESTSIZE,		! SIZE OF THE DESTINATION BUFFER
    RECORDSIZE,		! SIZE OF THE CURRENT RECORD
    BYTESTOMOVE,		! # OF BYTES TO BE TRANSFERRED TO USER'S BUFFER
    ASCIIBYTESLEFT;

REGISTER
     R5 = 5;

	TRACE ( 'PUTASCII' );

	%([ IF THIS IS A TTY DEVICE, THEN WE MUST RESET ALL BUFFER
	   COUNTERS AND POINTERS, ETC. IF IT IS NOT A TTY, WE
	   MUST MAKE SURE THAT WE ARE AT THE EOF ])%

	IF TTY 
	THEN
		BEGIN %(TO RESET BUFFER)%
		RST [ RSTBYTECOUNT ] = ZERO;				! CLEAR BUFFER
		RST [ RSTPAGPTR ] = POINT ( .CURENTBUFFERADR, 36, 7 );	!CLEAR BUFFER
		END %(OF IF TTY)%

	ELSE
		BEGIN %(TO CHECK FOR EOF)%
		IF NOT ENDOFFILE THEN USERERROR ( ER$NEF )		! MUST BE AT EOF
		END; %(F ELSE...)%

	%([ FOR SEQUENCED FILES, WE MUST FIRST CREATE A LINE NUMBER ])%

	IF SEQUENCED
	THEN
		BEGIN %( PUT A LSN )%
		CALLPUTLSN;					! WRITE LSN INTO FILE
		IF .RAB [ RABLSN ] IS PAGEMARKCODE
		THEN
			RETURN	!IGNORE USER'S RECORD IF PAGEMARK IS OUTPUT
		END;  %( OF PUT A LSN )%

	%([ SET UP FILE AND USER BUFFER POINTERS ])%

	USERPOINTER = POINT ( .RAB [ RABRBF ] ,36, 7 );			! GET USER ADDRESS
	RECORDSIZE = .RAB [ RABRSZ ];					! AGET # BYTES TO WRITE


	%([ THIS IS THE MAIN LOOP. IT CONTINUES UNTIL THE
	   ENTIRE USER RECORD HAS BEEN WRITTEN TO THE FILE ])%

	WHILE .RECORDSIZE GTR ZERO DO

		BEGIN
		%([ IS OUR BUFFER FULL? ])%

		IF .RST [ RSTBYTECOUNT ] IS PAGESIZE * ASCIIBYTPERWORD
		THEN CALLWRITEBUFFER;				! OUTPUT FULL BUFFER
		FILEPOINTER = .RST [ RSTPAGPTR ];		! FETCH FILE PONTER
		BYTESTOMOVE = .RECORDSIZE;			! ASSUM RECORD CAN FT IN FILE
		ASCIIBYTESLEFT = PAGESIZE * ASCIIBYTPERWORD - .RST [ RSTBYTECOUNT ];		! ASSUME ASCII FILE


		%([ USE THE RECORD SIZE OR THE BUFFER SPACE LEFT, WHICHEVER
		   IS SMALLER ])%

		IF .RECORDSIZE GTR .ASCIIBYTESLEFT THEN BYTESTOMOVE = .ASCIIBYTESLEFT;
		DESTSIZE = .BYTESTOMOVE;				! ASSUME SAME SIZE

		%([ DEBUGGING ])%

		LOOKAT ( '	FILEPTR: ', FILEPOINTER );
		LOOKAT ( '	# BYTES: ', BYTESTOMOVE );
		LOOKAT ( '	ASCII BYTES: ', ASCIIBYTESLEFT );

		%([ DO A MOVE-STRING WITH LEFT JUSTIFICATION TO FILE ])%

		
		TEMP1 = .USERPOINTER;
		TEMP2 = .FILEPOINTER;
		TEMP3 = .BYTESTOMOVE;
		TEMP4 = .DESTSIZE;
		IF MOVELEFT ( %(FROM)%		TEMP1,
				%(TO)%		TEMP2,
				%(SIZE)%	TEMP3,
				%(SIZE)%	TEMP4 ) IS FALSE
		THEN
			RMSBUG ( MSGMOVESTRING );		! MOVE-STRING FAILED

		%([ UPDATE OUR FILE AND BUFFER POINTERS ])%

		FILEPOINTER = .TEMP2;		! UPDATE POINTERS
		USERPOINTER = .TEMP1;


		RECORDSIZE = .RECORDSIZE - .BYTESTOMOVE;
		RST [ RSTPAGPTR ] = .FILEPOINTER;		! UPDATE POINTER

		%([ UPDATE # OF BYTES LEFT IN BUFFER ])%

		RST [ RSTBYTECOUNT ] = .RST [ RSTBYTECOUNT ] + .BYTESTOMOVE;
		END; %( OF WHILE LOOP )%



	%([ WE HAVE NOW MOVED THE ENTIRE RECORD FROM THE USER'S BUFFER
	   INTO THE INTERNAL RMS-20 FILE BUFFER.  WE MUST ALSO RESET
	   "HYBYTE" TO REFLECT THE HIGHEST BYTE IN THE FILE ])%

	RST [ RSTHYBYTE ] = .RST [ RSTHYBYTE ] + .RAB [ RABRSZ ];	! BUMP THE HIGH BYTE


	%([ IF WE ARE WRITING THIS RECORD TO A TERMINAL, THEN WE
	   SHOULD OUTPUT IT IMMEDIATELY ])%

	IF TTY THEN CALLWRITEBUFFER;

	RETURN

END; %( OF PUTASCII )%




! PUTLSN
! ======
!
!	THIS ROUTINE TAKES THE SEQUENCE NUMBER FROM THE USER'S RAB
!	AND INSERTS IT INTO THE FILE AS 5 ASCII DIGITS ( WITH BIT 35
!	TURNED ON ) FOLLOWED BY A HORIZONTAL TAB CHARACTER. NOTE
!	THAT THE FIRST DIGIT IS FORCED TO BE ON A WORD BOUNDARY.
!	ANY BYTES BETWEEN THE VFE OF THE LAST RECORD AND THE LSN WILL
!	BE NULLS.
!
! INPUT:
!	<NONE>

! OUTPUT:
!	<NONE>

! GLOBALS USED:
!	WRITEBUFFER
!
!
!		FORMAT OF A LSA RECORD
!		====== == = === ======
!
!	<FIVE-DIGIT-ASCII-NUMBER><BIT-35><TAB><THE-DATA-RECORD><VFE>
!
!
!		FORMAT OF A PAGEMARK
!		====== == = ========
!
!	<FIVE-ASCII-BLANKS><BIT-35><CR><FF><THREE-NULLS>
!
GLOBAL ROUTINE PUTLSN: NOVALUE  =
BEGIN

! DEVEL PTR TO NEXT WORD TO FILL IN BUFF (READ NEW BUFF IF NECES)
!
MACRO SET_WORDPTR =
BEGIN
	IF ( .RST [ RSTBYTECOUNT ] ) EQL PAGESIZE * ASCIIBYTPERWORD
	THEN CALLWRITEBUFFER;				! GET NEW BUF
	WORDPTR = .RST [RSTPAGPTR];		!NEED SUBFIELD
	IF .WORDPTR<30,6> NEQ 36		!WORD-ALIGNED ALREADY?
	THEN WORDPTR = .WORDPTR<RH> + 1		!ALIGN AT WORD BOUND
	ELSE WORDPTR = .WORDPTR<RH>;		!ALREADY THERE, JUST ISOL ADDR
END %;

! UPDATE THE MANY PTRS/CTRS ASSOC WITH WRITE TO BUF JUST DONE
!
MACRO UPD_BUFLOC(NBYTE$)=
BEGIN
	RST [RSTBYTECOUNT] = .RST [RSTBYTECOUNT] + NBYTE$;	!CNT OF WRIT CHARS IN BUF
	RST [RSTHYBYTE] = .RST [RSTHYBYTE] + NBYTE$;	!CNT OF WRIT CHARS SINC OP
	RST [RSTPAGPTR] = CH$PLUS(.RST [RSTPAGPTR], NBYTE$);	!UPD BYTE PTR
END %;

LOCAL
    BYTESLEFT,
    LINENUMBER,
    WORDPTR,
    TEMP;

REGISTER
     R5 = 5;

MAP
    WORDPTR:	POINTER;


	TRACE ( 'PUTLSN' );

	%([ FORCE PAGE POINTER TO A WORD BOUNDARY, LEAVING NULLS 
	   IN LAST PARTIAL WORD. ])%

	TEMP = ( ASCIIBYTPERWORD - .RST [ RSTBYTECOUNT ] MOD ASCIIBYTPERWORD ) MOD ASCIIBYTPERWORD;	! NO. BYTES TO SKIP
	UPD_BUFLOC(.TEMP);				!HOP OVER NULS

	LINENUMBER = .RAB [ RABLSN ];				! FETCH LINE NUMBER
	IF .LINENUMBER IS PAGEMARKCODE
	THEN	BEGIN %( TO WRITE A PAGE MARK )%
		SET_WORDPTR;			!PT TO NEXT AVAIL WORD IN BUF
		WORDPTR [ WHOLEWORD ] = PAGEMARK1;	! STORE 1ST WORD
		UPD_BUFLOC(5);			!RESET CNTERS
		SET_WORDPTR;			!RESET BUF PTR
		WORDPTR [ WHOLEWORD ] = PAGEMARK2;	! 2ND WORD
		UPD_BUFLOC(5);			!RESET CNTERS
		RETURN						! EXIT
	END; %( OF IF THIS IS A PAGE MARK )%


	SET_WORDPTR;				!PT TO NEXT AVAIL WORD IN BUF

	%([ FETCH THE  USER'S LINE NUMBER ])%

	IF .LINENUMBER GTR MAXLSN THEN USERERROR ( ER$LSN );

	%([ CONVERT IT TO DECIMAL AND OUTPUT IT TO FILE ])%

	IF BINARYTODECIMAL ( 	%(NUMBER)%	.LINENUMBER,
				%(DEST)%	.RST [RSTPAGPTR],
				%(SIZE)%	ASCIIBYTPERWORD ) IS FALSE
	THEN USERERROR ( ER$LSN );

	%([ SET BIT 35 IN THE LINE-NUMBER ])%

	WORDPTR [ WHOLEWORD ] = .WORDPTR [ WHOLEWORD ] OR LINENUMFLAG;
	UPD_BUFLOC(5);				!ACCT FOR LSN

	! NOW THE TAB
	SET_WORDPTR;
	(.WORDPTR)<29,7> = CHARTAB;		!PUT OUT TAB
	UPD_BUFLOC(1);				!ACCT FOR TAB

	RETURN

END; %( OF PUTLSN )%



! GETASCII
! ========

! THIS ROUTINE PROCESSES THE $GET MACRO FOR FILES WITH ASCII
!	AND LINE-SEQUENCED ASCII RECORD FORMAT.  FOR ASCII
!	FILES, IT TRANSFERS ONE RECORD INTO THE USER'S BUFFER,
!	WHERE A RECORD IS DEFINED AS BEING A STREAM OF ASCII
!	BYTES TERMINATED BY A VERTICAL FORMAT EFFECTOR.
!
!	FOR SEQUENCED FILES, FULL WORDS WILL BE TRANSFERED UNTIL
!	THE NEXT LINE-NUMBER IS FOUND.

! INPUT:
!	MOVEFLAG	FLAG FOR RECORD TRANSFER
!			TRUE:	MOVE THE RECORD ( $GET )
!			FALSE:	SKIP THE RECORD ( PARTIAL RECORD )

! OUTPUT:
!	NO. BYTES IN RECORD (NO. BYTES MOVED IF PARTIALFLAG HAS BEEN SET.)
!
! NOTES:
!	1) THIS ROUTINE SETS 'RSTRHSIZE' WHICH IS THE RECORD HEADER SIZE.
!	   FOR ASCII STREAM FILES THE RHSIZE IS ZERO (NO RECORD HEADER).
!	   FOR LSA STREAM FILES THE RHSIZE IS 6 IF RECORD BEGINS WITH
!	   A LSN, OR 10 IF THE RECORD IS A PAGEMARK. THIS FIELD IS USED
!	   BY THE $TRUNCATE PROCESSOR TO KNOW HOW MUCH TO SUBTRACT FROM
!	   RSTDATARFA TO FIND THE BEGINNING OF THE CURRENT PHYSICAL
!	   RECORD.
!
!	2) A "LOGICAL RECORD" IS DEFINED AS THE DATA THAT THE USER SEES.
!
!	3) A "PHYSICAL RECORD" IS DEFINED AS THE RECORD HEADER PLUS THE
!	   USER'S DATA.


GLOBAL ROUTINE GETASCII ( MOVEFLAG ) =
BEGIN

	ARGUMENT (MOVEFLAG,VALUE);

LOCAL
    TEMP1,
    TEMP2,
    TEMP3,
    TEMP4,
    FILEPOINTER,					! POINTER TO FILE BUFFER
    USERPOINTER,					! POINTER TO USER'S BUFFER
    EXITFLAG,					! FLAG FOR LEAVING THE LOOP
    RECORDSIZE,					! CURRENT LENGTH OF RECORD
    NEXTWORD,					! NEXT FILE WORD FOR LSA FILES
    MOVESTATUS,					! TEMP VARIABLE
    BUFFERSIZE,					! SIZE OF USER'S BUFFER
    BYTESMOVED,					!BYTES ACTU COPIED TO USER
    BYTESCANNED,				!BYTES SCANNED IN DOING COPY (LEADING NULS STRIPPED)
    BYTESTOMOVE;					! # OF BYTES IN THIS TRANSFER

MAP
    FILEPOINTER:	POINTER,
    USERPOINTER:	POINTER;


	TRACE ( 'GETASCII' );

	%([ IF EOF, DON'T BOTHER ])%

	IF ENDOFFILE THEN USERERROR ( ER$EOF );

	%([ SET UP USER BUFFER POINTER, ETC. ])%

	USERPOINTER = POINT ( .RAB [ RABUBF ] ,36, 7 );		!FORM BYTE POINTER
	BUFFERSIZE = .RAB [ RABUSZ ] * ASCIIBYTPERWORD;		! REMEMBER SIZE OF HIS BUFFER
	RECORDSIZE = ZERO;					! CLEAR TOTAL SIZE
	RAB [ RABRSZ ] = ZERO;					! CLEAR HIS RECORD SIZE
	EXITFLAG = FALSE;					! LOOP FOREVER



	%([ IF WE ARE SKIPPING A RECORD, THEN DONT USE A USER POINTER ])%

	IF .MOVEFLAG IS FALSE THEN USERPOINTER = ZERO;	! NO DATA WILL BE MOVED

	%([ PROCESS LSN IF READING AN LSA STREAM FILE ])%

	IF SEQUENCED AND ( PARTIALFLAG IS OFF )
	THEN
		BEGIN %( GET AN LSN )%
		CALLGETLSN;			! FETCH THE LINE-NUMBER
		IF .RAB [ RABLSN ] IS PAGEMARKCODE
		THEN
			BEGIN %( HANDLE PAGEMARK )%
			RST [ RSTRHSIZE ] = STMRHPM;	! SET RECORD HEADER SIZE
			SETFLAG ( RST [ RSTFLAGS ], FLGUPDPTR );	! MUST UPDATE POINTER
			RST [ RSTRSZ ] = ASCIIBYTPERWORD;	! RECORD SIZE=5
			IF .BUFFERSIZE ISNT ZERO
			THEN	%(MOVE THE PAGE MARK RECORD)%
				BEGIN
				REPLACEI ( USERPOINTER, CHARCR );
				REPLACEI ( USERPOINTER, CHARFF )
				END;
			RETURN PMRECSIZE		! SO, RECORDSIZE IS ZERO
			END   %( OF HANDLE PAGEMARK )%
		ELSE RST [ RSTRHSIZE ] = STMRHLSN	! SET RECORD HEADER SIZE
		END;   %( OF GET AN LSN )%

	IF NOT ( SEQUENCED )
	THEN RST [ RSTRHSIZE ] = STMRHASC;	! SET RECORD HEADER SIZE FOR ASCII STREAM FILE


	%([ THIS IS THE MAIN LOOP. IT CONTINUES UNTIL A VFE IS
	   SEEN OR THE USER'S BUFFER IS FILLED		])%

	UNTIL .EXITFLAG
	DO
		BEGIN

		%([ IF BUFFER IS EMPTY, THEN RE-FILL IT ])%

		IF .RST [ RSTBYTECOUNT ] IS ZERO THEN CALLREADBUFFER;
		IF ENDOFFILE THEN USERERROR ( ER$EOF );		! CHECK FOR EOF

		FILEPOINTER = .RST [ RSTPAGPTR ];		! GET BUFFER PTR
		BYTESTOMOVE = .RST [ RSTBYTECOUNT ];			! ASSUME WE WILL MOVE BUFFER
		IF ( .BUFFERSIZE LSS .BYTESTOMOVE ) AND ( .MOVEFLAG ISNT FALSE )
		THEN BYTESTOMOVE = .BUFFERSIZE;
	
		%([ DEBUGGING ])%
		LOOKAT ( '	BYTESTOMOVE:', BYTESTOMOVE );
		LOOKAT ( '	FILEPTR: ', FILEPOINTER );
	
		%([ WE WILL NOW MOVE THE ENTIRE RECORD 
		   UNTIL WE COME TO EITHER THE END
		   OF THE FILE, OR THE END OF THE
		   USER'S BUFFER, OR A VFE. WE WILL SAVE
		   THE STATUS OF THIS MOVE BECAUSE WE
		   HAVE TO DO SOME COMMON CLEAN-UP BEFORE
		   WE NEED TO CHECK IT ])%


		TEMP1 = .FILEPOINTER;
		TEMP2 = .USERPOINTER;
		TEMP3 = .BYTESTOMOVE;
		TEMP4 = .TEMP3;

		MOVESTATUS = MOVEASCIIRECORD (	%(FROM)%	TEMP1,
						%(TO)%		TEMP2,
						%(SIZE)%	TEMP3,
						%(SIZE)%	TEMP4 );

		%([ UPDATE POINTERS ])%

		FILEPOINTER = .TEMP1;
		USERPOINTER = .TEMP2;
		BYTESMOVED = .BYTESTOMOVE - .TEMP4 < RH >;	! SUB # OF UNMOVED BYTES
		BYTESCANNED = .BYTESTOMOVE - .TEMP3 < RH >;	! SUB # OF UNSCANNED BYTES
		RECORDSIZE = .RECORDSIZE + .BYTESMOVED;

		%([ IF WE ABORTED WITH A VFE, DEPOSIT IT ])%

		IF .MOVESTATUS IS FALSE
		THEN
			BEGIN
			IF .MOVEFLAG
			THEN BEGIN
				COPYNI ( FILEPOINTER, USERPOINTER );	!MOVE VFE
				RECORDSIZE = .RECORDSIZE+1;	!INCL VFE IN RECSIZ
			END;
			EXITFLAG = TRUE					! EXIT FROM LOOP
		END;   %( OF IF .MOVESTATUS IS FALSE )%


		%([ AT THIS POINT, WE HAVE DONE THE FOLLOWING:
	
		1 )  MOVED A FULL RECORD, OR
		2 )  FILLED THE USER'S BUFFER, OR
		3 )  EXHAUSTED THE CURRENT FILE BUFFER.
	
		])%
	
	
		%([ SET UP THE RECORD SIZE FIELD AND CHECK FOR
		   A RECORD WHICH IS TOO BIG FOR THE USER'S
		   BUFFER. ])%

		IF .MOVEFLAG 
		THEN
			BEGIN
			RAB [ RABRSZ ] = .RECORDSIZE;				! UPDATE USER'S RSZ

			%([ UPDATE NUMBER OF BYTES IN BUFFER ])%

			BUFFERSIZE = .BUFFERSIZE - .BYTESMOVED;

			%([ IF WE ARE STILL TRYING TO PROCES THE
			   RECORD,  BUT THE BUFFER IS FULL... ])%

			IF ( .EXITFLAG IS FALSE ) AND (.BUFFERSIZE LEQ ZERO ) %( WE HAVE FILLED THE BUFFER )%
			THEN
				BEGIN
				USRSTS = ER$RTB;					! SET PARTIAL RECORD
				USRSTV = .RECORDSIZE;				! RETURN PARTIAL RECORD SIZE
				SETFLAG ( RST [ RSTFLAGS ], FLGPARTIAL );	! REMEMBER THIS
				EXITFLAG = TRUE					! LEAVE
				END %( OF .BUFFERSIZE IS ZERO )%
			END; %( OF IF .MOVEFLAG )%
		
		%([ RESET THE BUFFER BYTE COUNT AND POINTER ])%

		RST [ RSTBYTECOUNT ] = .RST [ RSTBYTECOUNT ] - .BYTESCANNED;
		RST [ RSTPAGPTR ] = .FILEPOINTER			! RESET BUFFER PTR
		END; %( OF UNTIL EXITFLAG )%


	%([ STORE THE SIZE OF THIS RECORD IN THE USER'S RAB ])%

	RST [ RSTRSZ ] = .RECORDSIZE;					! PASS THE RECORD SIZE BACK

	%([ SET THE RST FLAG BIT WHICH TELLS FINDASC THAT
	   THE FILE POINTER (PAGPTR) MUST BE UPDATED BEFORE
	   THE NEXT OPERATION CAN BE DONE ])%

	SETFLAG ( RST [ RSTFLAGS ], FLGUPDPTR );

	%([ WE HAVE NOW DONE EVERYTHING AND WE CAN EXIT ])%

	RETURN .RECORDSIZE


END; %( OF GETASCII )%



! GETLSN
! ======

!     THIS ROUTINE PARSES A LINE SEQUENCE NUMBER. THE FILE
!	IS ASSUMED TO HAVE BEEN POSITIONED TO A WORD BOUNDARY BY
!	THE 'FINDASC' ROUTINE. THE TAB FOLLOWING THE LINE NUMBER
!	WILL BE STRIPPED OFF BY THIS ROUTINE. SEE THE 'PUTLSN'
!	ROUTINE FOR THE FORMAT OF A LSA RECORD. ALSO NOTE THAT
!	THIS ROUTINE HANDLES PAGE MARKS ( SEE THE 'PUTLSN' ROUTINE
!	FOR THE FORMAT OF A PAGE MARK. )
!

! INPUT:
!	<NONE>
!
! OUTPUT:
!	<NONE>
!
! GLOBALS USED:
!	<NONE>
!
! NOTES:
!
!	1.	THERE IS NO CHECK TO MAKE SURE THAT THE CHARACTER
!		WHICH IS STRIPPED OFF IS REALLY A "TAB".
!

GLOBAL ROUTINE GETLSN: NOVALUE  =
BEGIN

LOCAL
    TEMP,
    EXITFLAG,
    FILEPOINTER:	POINTER;



	TRACE ( 'GETLSN' );

	%([ MAKE SURE BUFFER IS NON-EMPTY ])%

	IF .RST [ RSTBYTECOUNT ] LSS 5			!IGNORE END OF REC CRUFT
	THEN
		BEGIN %( BUFFER IS EMPTY -- READ NEXT BUFFER )%
		CALLREADBUFFER;				! READ IN NEXT BUFFER
		IF ENDOFFILE THEN USERERROR (ER$EOF )	! HANDLE END-OF-FILE CONDITION
		END;

	TEMP = .RST [RSTPAGPTR];			!PREP TO GET SUBFLD
	IF .TEMP<30,6> NEQ 36			!WORD-ALIGNED ALREADY?
	THEN
		RST [ RSTPAGPTR ] = POINT ( .RST [ RSTPAGPTR ] + 1, 36, 7);	!INCR POINTER TO NEW WORD

	FILEPOINTER = .RST [ RSTPAGPTR ];		! GET POINTER TO LSN IN FILE

	%([ CHECK TO SEE IF THIS IS A PAGE MARK ])%

	IF .FILEPOINTER [ WHOLEWORD ] IS PAGEMARK1
	THEN
		BEGIN %( HANDLE PAGEMARK )%
		RAB [ RABLSN ] = PAGEMARKCODE;		! PASS PAGEMARK CODE BACK TO USER

		%([ MAKE CHECK TO SEE IF PAGE MARK SPANS PAGES ])%

		IF .RST [ RSTBYTECOUNT ] IS ASCIIBYTPERWORD
		THEN
			BEGIN %( PART OF PAGEMARK IS IN NEXT BUFFER )%
			CALLREADBUFFER;			! GET NEXT BUFFER
			RST [ RSTBYTECOUNT ] = .RST [ RSTBYTECOUNT ] - ASCIIBYTPERWORD;
			RST [ RSTPAGPTR ] = POINT ( .RST [ RSTPAGPTR ], 1, 7 );
			END   %( OF PART OF PAGEMARK IS IN NEXT BUFFER )%
		ELSE
			BEGIN %( ENTIRE PAGEMARK IS IN THIS BUFFER )%
			RST [ RSTBYTECOUNT ] = .RST [ RSTBYTECOUNT ] - PAGEMARKSIZE;
			RST [ RSTPAGPTR ] = POINT ( .RST [ RSTPAGPTR ] + 1, 1, 7);
			END;  %( OF ENTIRE PAGEMARK IS IN THIS BUFFER )%

		%([ UPDATE THE BYTE # OF THE CURRENT RECORD ])%

		RST [ RSTDATARFA ] = .RST [ RSTDATARFA ] +  ASCIIBYTPERWORD
		END   %( OF HANDLE PAGEMARK )%

	ELSE

		BEGIN %( HANDLE NORMAL LSN )%

	!+								!A56
	!  There may be a word of nulls next to a TOPS-10 buffer	!A56
	!  boundary, because some editors like to keep the LSN and	!A56
	!  the following TAB in the same buffer.			!A56
	!-								!A56

		IF (.FILEPOINTER [ WHOLEWORD ] IS ZERO )		!A56
			AND						!A56
		  ((.FILEPOINTER<RH> MOD LSNBUFSIZE ) EQL (LSNBUFSIZE - 1) )	!A56

		THEN %( NULL NEXT TO BUFFER BOUNDARY )%			!A56

			BEGIN						!A56
			CALLREADBUFFER;		! GET NEXT BUFFER	!A56
			IF ENDOFFILE THEN USERERROR (ER$EOF );	! HANDLE END-OF-FILE CONDITION	!A56
			FILEPOINTER = .RST [ RSTPAGPTR ];	! GET NEW VALUE			!A56
			END; %( OF HANDLE NULL AT END OF PAGE )%	!A56

		%([ CONVERT THE LINE NUMBER TO BINARY ])%
	
		IF DECIMALTOBINARY (	%(SOURCE)%	.FILEPOINTER,
					%(SIZE)%	ASCIIBYTPERWORD , 
					%(RESULT)%	TEMP ) IS FALSE
		THEN

			BEGIN
			FILEPROBLEM ( ER$LSN );			! BAD LINE SEQ NUMBER
			USEXITERR
			END; %(OF IF DEC-TO-BINARY FAILED)%

		%([ WE HAVE NOW CONVERTED THE LINE NUMBER...STORE IT ])%

		RAB [ RABLSN ] = .TEMP;	! STORE SEQUENCE NUMBER
		RST [ RSTBYTECOUNT ] = .RST [ RSTBYTECOUNT ] - ASCIIBYTPERWORD;
		RST [ RSTPAGPTR ] = POINT ( .RST [ RSTPAGPTR ] + 1, 36, 7 );	! POINT TO CHAR AFTER LINE NUMBER

		%([ CHECK FOR EMPTY BUFFER ])%

		IF .RST [ RSTBYTECOUNT ] IS ZERO
		THEN
			BEGIN %( BUFFER IS EMPTY -- READ NEXT BUFFER )%
			CALLREADBUFFER;				! READ IN NEXT BUFFER
			IF ENDOFFILE THEN USERERROR (ER$EOF )	! HANDLE END-OF-FILE CONDITION
			END;

		%([ WE CAN NOW STRIP OFF THE TAB CHARACTER AT
		   THE START OF THE RECORD. NOTE THAT THERE IS NO
		   ACTUAL CHECK TO MAKE SURE THAT THE FIRST
		   CHARACTER IS A TAB. ])%

		INCP ( RST [ RSTPAGPTR ] );			! STRIP OFF THE < TAB> CHAR
		RST [ RSTBYTECOUNT ] = .RST [ RSTBYTECOUNT ] - 1;	! COUNT THE <TAB> CHAR
		RST [ RSTDATARFA ] = .RST [ RSTDATARFA ] + ASCIIBYTPERWORD + 1
		END;  %( OF HANDLE NORMAL LSN )%

	%([ DONE. RETURN TO CALLER. ])%

	RETURN

END; %(OF GETLSN )%
END
ELUDOM