Google
 

Trailing-Edge - PDP-10 Archives - AP-D471B-SB_1978 - msgin.bli
There are no other files named msgin.bli in the archive.
!***COPYRIGHT (C) 1974, 1975, 1976, 1977 DIGITAL EQUIPMENT CORP., MAYNARD, MASS.***
MODULE MSGIN(RESERVE(#11,#12,#13,#14),SREG=#17,FREG=#16,DREGS=4,
	     VREG=#15,MLIST,TIMER=EXTERNAL(SIX12),FSAVE)=
BEGIN

	GLOBAL WHYERROR;	!ERROR CODES FOR ENTRY INTO THE ERROR LEAF

REQUIRE DATA.BLI;		!EVERYONE NEEDS THIS NEAT THING!!
EXTERNAL	COMPARE,
		UNLINK,
		MOVE;

COMMENT;

! ROUTINE SKIPCHUNKS
! ======= ==========
! THIS ROUTINE SKIPS THE SPECIFIED NUMBER OF CHARACTERS GIVEN.  IT
! WILL ADVANCE CHUNKS AS REQUIRED TO ACCOMPLISH THIS.
! CALLED WITH	1) POINTER TO FIRST CHUNK
!		2) NUMBER OF CHARACTERS TO SKIP
!		3) FLAG INDICATING WHETHER SKIPPED CHUNKS ARE TO BE DELETED
! RETURNS:	LH) CHARACTERS UNSKIPPED IN THIS CHUNK (READY FOR INPUT TO MAKEBP)
!		RH) CHUNKPTR
!		BOTH 0 IF WE RUN OFF THE END

GLOBAL ROUTINE SKIPCHUNKS( CHUNKPTR, COUNT, FLAG) =
    BEGIN
	REGISTER
		C,
		CHUNK;
	MAP	FORMAT CHUNK;

	C _ .COUNT;				! PUT ARGS IN REGISTERS
	CHUNK _ .CHUNKPTR;

	WHILE .C GTR .CHUNK[C0BCNT] AND .CHUNK NEQ 0 DO
	    BEGIN
		C _ .C - .CHUNK[C0BCNT];
		IF .FLAG THEN DELCHNK(.CHUNK);
		CHUNK _ .CHUNK[C0LINK]
	    END;

	IF .CHUNK NEQ 0 THEN		! IF WE DIDN'T GO OFF THE END
	    BEGIN
		CHUNK<LH> _ .C;		! RETURN XWD COUNT, CHUNKPTR
		RETURN .CHUNK
	    END;

	0				! ELSE RETURN BAD END

    END;
COMMENT;

! ROUTINE MAKEBP
! ======= ======
! THIS ROUTINE MAKES A BYTE POINTER GIVEN A CHUNKPTR AND THE NUMBER OF
! CHARACTERS TO SKIP
! CALLED WITH:	1) POINTER TO THE CHUNK
!		2) CHARACTERS TO SKIP
! RETURNS:	A BYTE POINTER TO THE FIRST CHARACTER AFTER THE SKIP
! NOTE: THE CHARACTER MUST BE IN THE CHUNK GIVEN.

GLOBAL ROUTINE MAKEBP( CHUNKPTR, COUNT) =
    BEGIN
	MAP	FORMAT CHUNKPTR;
	REGISTER
		OUT;

	OUT _ 0;
	OUT<SIZ> _ ASCIISIZE;
	OUT<POS> _ 36 - (.COUNT MOD ASCIIBYTESPERWORD ) * ASCIISIZE;
	OUT<RH> _ CHUNKPTR[C0DATA] + .COUNT / ASCIIBYTESPERWORD;

	.OUT
    END;
COMMENT;

! ROUTINE TC
! ======= ==
! TC PICKS THE TRANSACTION CODE OUT OF THE MESSAGE

ROUTINE TC( MHPTR, SRCPTR)=
    BEGIN
	REGISTER
		CHAR,
		COUNT,
		BPIN,
		BPOUT;
	LOCAL
		TRCODE,
		CHUNKPTR,
		CHARLEFT;
	MAP FORMAT MHPTR;
	MAP FORMAT CHUNKPTR;
	MAP FORMAT SRCPTR;

	MACRO
		NEXTCHAR = 
			BEGIN
				WHILE ( CHARLEFT _ .CHARLEFT - 1 ) LSS 0 DO	! IF NO CHARACTERS LEFT
									! IN THIS CHUNK GET ANOTHER
				    BEGIN
					IF ( CHUNKPTR _ .CHUNKPTR[C0LINK]) EQL 0 THEN
						RETURN (RETMEM ( .TRCODE, .TRCW ); -1);
					BPIN<RH> _ CHUNKPTR[C0DATA];
					BPIN<POS> _ 36;
					CHARLEFT _ .CHUNKPTR[C0BCNT]
				    END;
				CHAR _ SCANI(BPIN);
				IF .CHAR GEQ #141 AND .CHAR LEQ #172 THEN CHAR _ .CHAR - #40 ELSE .CHAR
			END$,
		STORECHAR = (REPLACEI(BPOUT, .CHAR))$;

	CHUNKPTR _ .MHPTR[M0INCHNK];
	TRCODE _ GETMEM(.TRCW);		! GET ROOM TO STORE A TRANSACTION CODE
	ZERO( .TRCODE, .TRCODE + .TRCW - 1);	! CLEAR THE TRANSACTION CODE FIELD
	IF ( CHUNKPTR _ SKIPCHUNKS( .CHUNKPTR, .FILLRB, FALSE)) EQL 0 THEN
			RETURN (RETMEM ( .TRCODE, .TRCW ); -1);
	COUNT _ .CHUNKPTR<LH>;
	BPIN _ MAKEBP( .CHUNKPTR, .COUNT);		! MAKE THE INPUT BYTE POINTER
	BPOUT _ (.TRCODE)<36,7>;				! AND THE OUTPUT BYTE POINTER
	CHARLEFT _ .CHUNKPTR[C0BCNT] - .COUNT;

	COUNT _ 0;

	IF .TRCDEL<LH> NEQ 0 THEN
	    BEGIN
		WHILE (( COUNT _ .COUNT + 1) LEQ .TRCLEN) AND (NEXTCHAR NEQ .TRCDEL<RH>) DO STORECHAR;
		IF .COUNT LEQ .TRCLEN THEN COUNT _ .COUNT + 1;
	    END
	    ELSE
	    BEGIN
		WHILE ( COUNT _ .COUNT + 1) LEQ .TRCLEN DO
		    BEGIN
			NEXTCHAR;
			STORECHAR
		    END
	    END;
	SRCPTR[S0SOT] _ .FILLRB + .FILLRC + .COUNT - 1;
	.TRCODE

    END;
COMMENT;

! ROUTINE DECODE
! ======= ======

ROUTINE DECODE(MHPTR,SRCPTR)=
    BEGIN
	REGISTER
		TCPTR,
		TCTAB,
		TCWORDS;
	LOCAL
		LEAFADDR,
		LEAF;
	MAP FORMAT LEAFADDR;
	MAP FORMAT MHPTR;
	MAP FORMAT SRCPTR;

	MACRO	ERROR = RETURN -1 ^ 18 OR$;
	LABEL	THIS;

	IF ( TCPTR _ TC(.MHPTR, .SRCPTR) ) EQL -1 THEN
		BEGIN
			WHYERROR _ 3;	!ERROR = UNKNOWN TRCODE
			ERROR ERLEAF
		END;
	TCTAB _ TRCODE;
	TCWORDS _ .TRCW;

	LEAF _
	    BEGIN
		THIS: INCR COUNT FROM 0 TO .TRCODE[-1] - 1 DO
		    BEGIN
			IF COMPARE(.TCPTR, .TCTAB, .TCWORDS) THEN LEAVE THIS WITH .COUNT;
			TCTAB _ .TCTAB + .TCWORDS
		    END
	    END;

	RETMEM( .TCPTR, .TCWORDS);		! GIVE BACK THE MEMORY TC GOT

	IF .LEAF LSS 0 THEN
	    BEGIN
		WHYERROR _ 3;	!ERROR = UNKNOWN TRCODE
		ERROR ERLEAF
	    END
	    ELSE
	    BEGIN
		LEAFADDR _ .LFADDR[.LEAF];
		IF .SRCPTR[S0LFSTS(.LEAFADDR[N0LLFNO],2)] NEQ 0 THEN
		    BEGIN
			WHYERROR _ 4;	!ERROR = DISABLED TERMINAL
			ERROR ERLEAF
		    END
		    ELSE IF .LEAFADDR[N0ED] THEN
					    BEGIN
						WHYERROR _ 4;	!ERROR = DISABLED AT LEAF
						ERROR ERLEAF
					    END
	    END;

	LEAFADDR<LH> _ .LEAF;
	.LEAFADDR

    END;
EXTERNAL	UNLINK,
		LINK,
		DECREMENT,
		INSERT,
		CHKRUN,
		NEXTINTSN,
		BUILD,
		DCHNKS,
		INLOGMSG,
		CHKGH,
		CHKMSG,
		ROLMSG,
		FINDPORT,
		SONLEAF,
		ERLEAF;

COMMENT;

!LAST MODIFIED:		30 JUL 76  BY  CDO


! ROUTINE MSREAD
! ======= ======

! CALLED WHEN THERE IS A BUFFER TO READ
! RETURNS TRUE IF EVERYTHING NORMAL
! FALSE IF SOMETHING WAS WRONG

GLOBAL ROUTINE MSREAD =
    BEGIN

	REGISTER
	    CHUNKPTR,
	    SRCPTR,
	    MHPTR,
	    GHPTR;

	LOCAL
	    COUNT,
	    MPPPTR,
	    LEAFPTR,
	    PORT,
	    TEMP,
	    UDX,
	    TRCODEINDEX,
	    ENDI;

	MAP FORMAT CHUNKPTR;
	MAP FORMAT SRCPTR;
	MAP FORMAT PORT;
	MAP FORMAT TEMP;
	MAP FORMAT MHPTR;
	MAP FORMAT LEAFPTR;
	MAP FORMAT GHPTR;
	MAP FORMAT LFTAB;

	MACRO PURGEFLAG = SRCPTR[S0PURGE]$;

	!BEGIN!

	! GET A CHUNK
	! IF THERE ISN'T ONE TO GET THEN RETURN WITH A FALSE VALUE
	IF (CHUNKPTR _ INMSG()) EQL 0 THEN RETURN FALSE;

	! BREAK UP THE VALUE RETURNED BY INMSG INTO ITS COMPONENTS
	UDX _ .CHUNKPTR<LH>;
	CHUNKPTR _ .CHUNKPTR<RH>;
	CHUNKPTR[C0LINK] _ 0;			! MAKE SURE THE LINK IS ZERO


	! GET THE END INDICATOR
	ENDI _ .CHUNKPTR[C0ENDI];

	! FIND OUT WHO THE CHUNK COMES FROM
	SRCPTR _ 0;
	IF ( PORT _ FINDPORT( .UDX) ) NEQ 0 THEN
		IF ( SRCPTR _ .PORT[PT0SRCPTR] ) EQL 0 THEN SRCPTR _ .PORT[PT0TMPSRCPTR];
	PORT[PT0CARRIER] _ TRUE;		!DATA IMPLIES CARRIER
	IF .SRCPTR EQL 0 THEN
	    BEGIN
		RETMEM(.CHUNKPTR,.CHUNKPTR[C0WORDS]+C0HEADSIZE);	! IF THE SENDER IS UNKNOWN ZAP THE CHUNK
		RETURN FALSE						! AND RETURN FALSE
	    END;

	! IF WE ARE PURGING MESSAGES FROM THIS SOURCE THEN SEE IF WE
	!    SHOULD STOP PURGING.  BUT IN ANYCASE RETURN THE CHUNK TO FREE
	!    CORE
	IF .PURGEFLAG THEN
	    BEGIN
		IF .ENDI GEQ EGI THEN PURGEFLAG _ FALSE;
		RETMEM(.CHUNKPTR,.CHUNKPTR[C0WORDS]+C0HEADSIZE);
		SRCPTR[S0TSN] _ SRCPTR[S0GHPTR] _ 0;
		RETURN TRUE
	    END;

	! IF TSN NOT ALREADY ASSIGNED THEN GET ONE
	IF .SRCPTR[S0TSN] EQL 0 THEN SRCPTR[S0TSN] _ NEXTINTSN();

	! LINK CHUNK TO SRCTAB
	IF (TEMP _ .SRCPTR[S0LCHNK]) EQL 0 THEN SRCPTR[S0LCHNK] _ SRCPTR[S0FCHNK] _ .CHUNKPTR
	    ELSE SRCPTR[S0LCHNK] _ TEMP[C0LINK] _ .CHUNKPTR;

	! IF NOT MESSAGE OR GROUP THEN EXIT MSREAD NOW
	IF .ENDI LEQ ESI THEN RETURN TRUE;

	! OTHERWISE WE HAVE AT LEAST A MESSAGE, SO MAKE A MESSAGE HEADER
	MHPTR _ CREATEMH(0);

	! FILL IN CHUNK POINTERS IN MESSAGE HEADER
	MHPTR[M0INCHNK] _ MHPTR[M0OUTCHNK] _ .SRCPTR[S0FCHNK];

	! CLEAR CHUNK POINTERS IN SRCTAB
	SRCPTR[S0CHUNKS] _ 0;

	! DATE & TIME STAMP THE CREATED MESSAGE HEADER
	STAMP(MHPTR[M0DATE],MHPTR[M0TIME]);

	IF (GHPTR _ .SRCPTR[S0GHPTR]) NEQ 0 THEN	! IF GH ALREADY EXISTS
	    BEGIN
		MHPTR[M0SOT] _ 0;

		IF .INLOGGING THEN
		    INLOGMSG(	.SRCPTR[S0TSN] ^ 18,
				    .MHPTR[M0DATE],
				    .MHPTR[M0TIME],
				    SRCPTR[ S0ID ],		! NOTE POINTERPNOT VALUE
				    0,
				    .MHPTR[M0INCHNK]);
		IF .GHPTR[G0CHKPNT] THEN
		    BEGIN
			MHPTR[M0DSKADDR] _ CHKMSG( .GHPTR[G0DSKGHADDR],
							 .MHPTR[M0DATE],
							 .MHPTR[M0TIME],
							 .MHPTR[M0INCHNK],
							 .MHPTR[M0SOT]);
			IF .GHPTR[G0ONDSK] THEN ! IF GROUP IS NOT TO BE KEPT IN CORE
			    BEGIN
				DCHNKS(.MHPTR);		! ZAP THE CHUNKS
				MHPTR[M0CHNKS] _ 0		! AND MARK IT OUT
			    END
		    END
		    ELSE
			IF .GHPTR[G0ONDSK] THEN	!IF BEING ROLLED OUT
			    BEGIN
				MHPTR[M0DSKADDR] _ ROLMSG( .GHPTR[G0DSKGHADDR],
							 .MHPTR[M0INCHNK],
							 .MHPTR[M0SOT]);
				MHPTR[M0CHNKS] _ 0
			    END;
		IF .ENDI EQL EGI THEN GHPTR[G0ENDI] _ 1; %EGI%	! SET END INDICATOR IN GH
		INSERT(.MHPTR,.GHPTR);	!ATTACH MESSAGE

	    END
	    ELSE
	    BEGIN				! IF GH DOESN'T EXIST THEN DECODE TRANSACTION TYPE
		LEAFPTR _ DECODE(.MHPTR,.SRCPTR);
		TRCODEINDEX _ .LEAFPTR<LH>;		! BREAK UP THE VALUE RETURNED FROM TRCODE
		LEAFPTR _ .LEAFPTR<RH>;

		IF .PORT[PT0SRCPTR] EQL 0 AND .LEAFPTR<RH> NEQ SONLEAF<0,0> THEN
		    BEGIN			! IF NOT SIGNED ON AND NOT SIGNING ON
			LEAFPTR _ ERLEAF;
			WHYERROR _ 1;		! ERROR = NOT SIGNED ON
			TRCODEINDEX _ #777777
		    END;

		MHPTR[M0SOT] _ .SRCPTR[S0SOT];			!SAVE NUMBER OF CHARACTERS TO SKIP
		SRCPTR[S0SOT] _ 0;
		!CHECK FOR PROPER LENGTH MESSAGE HERE ALSO
		COUNT_0;
		CHUNKPTR_.MHPTR[ M0INCHNK ];
		UNTIL .CHUNKPTR EQL 0
		DO BEGIN COUNT_.COUNT+.CHUNKPTR[ C0BCNT ];
			CHUNKPTR_.CHUNKPTR[ C0LINK ]
		   END;
		IF .MHPTR[ M0SOT ] GTR .COUNT THEN
					BEGIN
					WHYERROR _ 2;	!ERROR = NOT ENOUGH DATA
					TRCODEINDEX _  #777777;
					LEAFPTR _ ERLEAF
					END;

		IF .INLOGGING THEN
			    INLOGMSG(	.SRCPTR[S0TSN] ^ 18,
					    .MHPTR[M0DATE],
					    .MHPTR[M0TIME],
					    SRCPTR[S0ID],		! NOTE POINTER NOT VALUE
					    IF .TRCODEINDEX NEQ #777777 THEN
						TRCODE[.TRCODEINDEX*.TRCW] ELSE .TRCODEINDEX,
					    .MHPTR[M0INCHNK]);

		! MAKE A GROUP HEADER, ZERO IT, AND LINK IT TO A LEAF
		GHPTR _ CREATEGH(LEAFPTR[N0GHS]);

		SRCPTR[S0GHPTR] _ .GHPTR;		! TELL SRCPTR WHERE THE GH IS
		! STORE POINTER TO SENDER IN THE GH
		GHPTR[G0SENDER] _ SRCPTR[S0ID];		!NOTE: ADDRESS NOT VALUE!
		! STORE POINTERS TO THE MESSAGE IN THE GH
		GHPTR[G0FMHPTR] _ GHPTR[G0LMHPTR] _ GHPTR[G0OUTMH] _ .MHPTR;
		GHPTR[G0LFPTR] _ .LEAFPTR;		! SAVE GROUPS PARENT LEAF IN THE GH
		GHPTR[G0LHTSN] _ .SRCPTR[S0TSN];	! SAVE TSN IN GH

		IF .ENDI EQL EGI THEN GHPTR[G0ENDI] _ 1;		! SET END INDICATOR IN GH

		IF (.LEAFPTR<RH> LSS ERLEAF<0,0>) AND .CHECKPOINTING AND
			.LEAFPTR[N0CHKPNT] THEN
		    BEGIN	!MUST FAILSOFT THIS REAL TRANSACTION
			GHPTR[G0DSKGHADDR] _ CHKGH( .LEAFPTR[N0LLFNO],	! CHECKPOINT THE GROUP
				    .GHPTR[G0TSN],
				    .GHPTR[G0SENDER],
				    .MHPTR);

							! AND STORE THE DISK GROUP HEADER ADDRESS
			GHPTR[G0CHKPNT] _ TRUE		! THIS IS BEING CHECKPOINTED
		    END;

		CHKRUN(.LEAFPTR, 1, .GHPTR);	! INCREMENT THE GROUP COUNT OF THE LEAF,
						    ! ROLL OUT IF QUOTA EXCEEDED,
						    ! AND GET ANYONE OUT OF WAITING IF WE CAN

	    END;
	! IF END OF GROUP THEN CLEAN UP SRCTAB
	IF .ENDI EQL EGI THEN SRCPTR[S0TSN] _ SRCPTR[S0GHPTR] _ 0;

	TRUE
    END;
END;