Google
 

Trailing-Edge - PDP-10 Archives - TOPS-20_V6.1_DECnetSrc_7-23-85 - mcb/tkb36/tfio20.bli
There is 1 other file named tfio20.bli in the archive. Click here to see a list.
!<REL4A.TKB-VNP>FIO20.BLI.8,  3-Dec-79 14:30:05, Edit by SROBINSON
MODULE FIO20 (					!File I/O for TOPS-20
		IDENT = 'X2.0'
		) =
BEGIN
!
!                    COPYRIGHT (c) 1980, 1981, 1982
!                    DIGITAL EQUIPMENT CORPORATION
!                        Maynard, Massachusetts
!
!     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  which  is  not supplied by
!     DIGITAL.
!

!++
! FACILITY: TKB-20 and VNP-20
!
! ABSTRACT:
!
!	This module does all I/O operations associated with the processing
!	of files by VNP-20 and TKB-20. It also contains routines that are
!	system dependent.
!
!	The I/O routines supported are:
!		RESET_ALL - initialization of I/O system
!		OPEN - open a file
!		CLOSE - close a file
!		INPUT - get data from a file
!		OUTPUT - put data onto a file
!
!	The system dependent routines are:
!		STOP_PROGRAM - terminate program
!
!	Channel 0 is always the terminal. Other channels are assigned at
!	will and are an artifact of programs written for TOPS-10 I/O.
!
! ENVIRONMENT: TOPS-20 User Mode
!
! AUTHOR: Scott G. Robinson, CREATION DATE: 25-NOV-78
!
! MODIFIED BY:
!
!	Scott G. Robinson, 5-MAR-79 : VERSION X0.2
!	- Modify to use JSYS_CALL macro to resolve register conflicts
!
!	Scott G. Robinson, 13-JUN-79 : VERSION X0.3
!	- Add routine STOP_PROGRAM
!-----------------------------------------------------------------------
!
!	Scott G. Robinson, 3-DEC-79 : Version X2.0
!	- Ensure DECnet-10 Compatibility
!
! 	, : VERSION
! 01	-
!--

!
! TABLE OF CONTENTS:
!

FORWARD ROUTINE
    RESET_ALL : NOVALUE,			!Reset all I/O
    OPEN,					!Open a file
    CLOSE : NOVALUE,				!Close a file
    INPUT,					!Read from a file
    OUTPUT : NOVALUE,				!Write on a file
    STOP_PROGRAM : NOVALUE;			!Terminate execution

!
! INCLUDE FILES:
!

LIBRARY 'BLI:MONSYM';

LIBRARY 'BLI:TENDEF';

!
! MACROS:
!

MACRO
    JSYS_CALL (TYPE, FUNC, AC1, AC2, AC3, AC4) =
	BEGIN
	REGISTER T1=1,T2=2,T3=3,T4=4;
	LOCAL VALUE;
	BUILTIN JSYS;
%IF NOT %NULL(AC1) %THEN T1=.AC1; %FI
%IF NOT %NULL(AC2) %THEN T2=.AC2; %FI
%IF NOT %NULL(AC3) %THEN T3=.AC3; %FI
%IF NOT %NULL(AC4) %THEN T4=.AC4; %FI
	VALUE = JSYS(TYPE,FUNC,T1,T2,T3,T4);
%IF NOT %NULL(AC1) %THEN %IF %DECLARED(AC1) %THEN AC1=.T1; %FI %FI
%IF NOT %NULL(AC2) %THEN %IF %DECLARED(AC2) %THEN AC2=.T2; %FI %FI
%IF NOT %NULL(AC3) %THEN %IF %DECLARED(AC3) %THEN AC3=.T3; %FI %FI
%IF NOT %NULL(AC4) %THEN %IF %DECLARED(AC4) %THEN AC4=.T4; %FI %FI
	.VALUE
	END	%;

!
! EQUATED SYMBOLS:
!

LITERAL
    DEBUG = 0,
    LEN_LINE_BUFF = 160;

!
! OWN STORAGE:
!

OWN
    CHAN_MODE : VECTOR [16],			!1=Character, 2=Word
    CHAN_DIRECTION : VECTOR [16],		!0=Input, 1=Output
    CHAN_JFN : VECTOR [16],			!Channel to JFN Mapping
    CHAN_NEXT : VECTOR [16],			!Next byte in word mode
    LINE_BUFF : VECTOR [CH$ALLOCATION (LEN_LINE_BUFF)];	!Input line buffer

!
! BOUND STORAGE FOR TERMINAL INPUT PROCESSING
!

BIND
    LINE_LEN = CHAN_MODE [0],
    LINE_STATUS = CHAN_DIRECTION [0],
    LINE_PTR = CHAN_NEXT [0];

!
! EXTERNAL REFERENCES:
!

EXTERNAL ROUTINE
    ERROR : NOVALUE,				!Programming Error
    ERRMSG : NOVALUE;				!Standard Error Message
GLOBAL ROUTINE RESET_ALL : NOVALUE = 		!Reset all I/O

!++
! FUNCTIONAL DESCRIPTION:
!
!	Initializes the I/O system
!
! FORMAL PARAMETERS:
!
!	NONE
!
! IMPLICIT INPUTS:
!
!	NONE
!
! IMPLICIT OUTPUTS:
!
!	NONE
!
! COMPLETION CODES:
!
!	NONE
!
! SIDE EFFECTS:
!
!	All Files currently open are dropped
!
!--

    BEGIN

    BIND
	ROUTINE_NAME = UPLIT (%ASCIZ'RESET_ALL');

    JSYS_CALL (0, RESET);
    END;					!of RESET_ALL
GLOBAL ROUTINE OPEN (CHANX, FNAME, MODE, IO, DEFEXT) : = 	!Open a File

!++
! FUNCTIONAL DESCRIPTION:
!
!	Opens a file on channel "CHANX" with name "FNAME" in mode "MODE"
!	 with direction "IO" with default extension "DEFEXT".
!
! FORMAL PARAMETERS:
!
!	CHANX - Contains the channel number to associate with the file
!	FNAME - Points at the file name
!	MODE - File Mode (1=Character, 2= Word)
!	IO - Direction (0=Input,1=Output)
!	DEFEXT - Default extension if none specified in FNAME
!
! IMPLICIT INPUTS:
!
!	NONE
!
! IMPLICIT OUTPUTS:
!
!	NONE
!
! ROUTINE VALUE:
!
!	1 If OPEN Successful, 0 If not.
!
! SIDE EFFECTS:
!
!	Modifies OWN storage to reflect associated file information.
!
!--

    BEGIN

    BIND
	ROUTINE_NAME = UPLIT (%ASCIZ'OPEN');

    LOCAL
	CHAN,
	GTJFN_BLOCK : VECTOR [9],
	BYTE_SIZE,
	AC1,
	AC2,
	AC3;

!
! Check on legality of channel number
!
    CHAN = .CHANX;

    IF (.CHAN EQL 0)
    THEN
	ERROR (UPLIT (%ASCIZ'May not OPEN channel 0 - OPEN'))
    ELSE

	IF ((.CHAN GTR 15) OR (.CHAN LSS 0))
	THEN
	    ERROR (UPLIT (%ASCIZ'Invalid Channel Number - OPEN'))
	ELSE

	    IF (.CHAN_JFN [.CHAN] NEQ 0)
	    THEN
		ERROR (UPLIT (%ASCIZ'Attempting to OPEN an already OPEN channel - OPEN'))
	    ELSE
!
! We now have what appears to be a valid request: The channel number is within
!  range and it is not open.
!
! Build a GTJFN Block to attempt and access the file.
!
		BEGIN
		GTJFN_BLOCK [$GJGEN] = (CASE .IO FROM 0 TO 1 OF
		    SET
		    [0] : GJ_OLD;
		    [1] : GJ_FOU + GJ_NEW;
		    [OUTRANGE] : -1;
		    TES);

		INCR FOO FROM $GJDEV TO $GJJFN DO
		    GTJFN_BLOCK [.FOO] = 0;

		GTJFN_BLOCK [$GJSRC] = %O'377777377777';	!.NULIO,,.NULIO
		GTJFN_BLOCK [$GJEXT] = CH$PTR (.DEFEXT);
		AC2 = CH$PTR (.FNAME);
		AC1 = GTJFN_BLOCK;

		IF NOT JSYS_CALL (1, GTJFN, AC1, AC2)	!Get the JFN
		THEN
		    BEGIN			!and if in error
		    ERRMSG (0, 2, ROUTINE_NAME, .FNAME, 0, 0, 0);
		    RETURN 0
		    END;

		CHAN_JFN [.CHAN] = .AC1;	!Save returned JFN
		CHAN_MODE [.CHAN] = .MODE;	! and mode
		CHAN_DIRECTION [.CHAN] = .IO;	! with direction
		CHAN_NEXT [.CHAN] = -1;		!Indicate Initial State
!
! Because we were apparently successful in accessing the file, open
! it.
!
		BYTE_SIZE = (CASE .MODE FROM 1 TO 2 OF
		    SET
		    [1] : 7;			!Character mode
		    [2] : 18;			!16-bit word mode
		    [OUTRANGE] : 0;		!Use default
		    TES);
		AC2 = FLD (.BYTE_SIZE, OF_BSZ) + (CASE .IO FROM 0 TO 1 OF
		    SET
		    [0] : OF_RD;
		    [1] : OF_WR;
		    [OUTRANGE] : 0;
		    TES);
		AC1 = .CHAN_JFN [.CHAN];

		IF NOT JSYS_CALL (1, OPENF, AC1, AC2)
		THEN
		    BEGIN			!OPENF Failed!!!
		    ERRMSG (0, 3, ROUTINE_NAME, .FNAME, 0, 0, 0);
		    CHAN_JFN [.CHAN] = 0;
		    RETURN 0
		    END;

		END;

    1
    END;					!End of OPEN
GLOBAL ROUTINE CLOSE (CHANX) : NOVALUE = 	!Close a channel

!++
! FUNCTIONAL DESCRIPTION:
!
!	Close a file channel
!
! FORMAL PARAMETERS:
!
!	CHANX - the channel to close
!
! IMPLICIT INPUTS:
!
!	NONE
!
! IMPLICIT OUTPUTS:
!
!	NONE
!
! COMPLETION CODES:
!
!	NONE
!
! SIDE EFFECTS:
!
!	Minipulation of the OWN data base occurs
!
!--

    BEGIN

    BIND
	ROUTINE_NAME = UPLIT (%ASCIZ'CLOSE');

    LOCAL
	CHAN,
	AC1;

!
! Validate Channel number
!
    CHAN = .CHANX;

    IF (.CHAN EQL 0)
    THEN
	ERROR (UPLIT (%ASCIZ'You May Not Close Channel 0 - CLOSE'))
    ELSE

	IF ((.CHAN LSS 0) OR (.CHAN GTR 15))
	THEN
	    ERROR (UPLIT (%ASCIZ'Invalid Channel Number - CLOSE'))
	ELSE

	    IF (.CHAN_JFN [.CHAN] EQL 0)
	    THEN
		ERROR (UPLIT (%ASCIZ'Channel is not OPEN - CLOSE'))
	    ELSE
		BEGIN
		AC1 = .CHAN_JFN [.CHAN];
		JSYS_CALL (1, CLOSF, AC1);
		CHAN_JFN [.CHAN] = 0;
		END;

    END;					!End of CLOSE
GLOBAL ROUTINE INPUT (CHANX) : = 		!Read from file

!++
! FUNCTIONAL DESCRIPTION:
!
!	Returns the next character (or PDP-11) word from a file.
!
! FORMAL PARAMETERS:
!
!	CHANX - the channel number associated with the file
!
! IMPLICIT INPUTS:
!
!	NONE
!
! IMPLICIT OUTPUTS:
!
!	NONE
!
! ROUTINE VALUE:
!
!	The character or word is returned.
!	If EOF or an ERROR is reached then -1 is returned.
!
! SIDE EFFECTS:
!
!	NONE
!
!--

    BEGIN

    BIND
	ROUTINE_NAME = UPLIT (%ASCIZ'INPUT');

    LOCAL
	CHAN,
	CHAN_CHAR,
	AC1,
	AC2,
	AC3;

!
! Determine whether the channel is for the terminal or a file then
!  process accordingly.
!
    CHAN = .CHANX;

    IF (.CHAN EQL 0)
    THEN
	BEGIN

	IF (.LINE_PTR EQL 0)
	THEN
	    BEGIN
	    AC3 = 0;
	    AC2 = RD_TOP + RD_RAI + LEN_LINE_BUFF;
	    AC1 = CH$PTR (LINE_BUFF);
	    LINE_STATUS = (IF NOT JSYS_CALL (1, RDTTY, AC1, AC2, AC3) THEN -1 ELSE .AC2);
	    LINE_PTR = CH$PTR (LINE_BUFF);
	    LINE_LEN = LEN_LINE_BUFF - (.LINE_STATUS AND %O'777777');
	    END;

	CHAN_CHAR = CH$RCHAR_A (LINE_PTR);

	IF ((LINE_LEN = .LINE_LEN - 1) EQL 0) THEN LINE_PTR = 0;

	END
    ELSE
	BEGIN

	IF ((.CHAN LSS 0) OR (.CHAN GTR 15))
	THEN
	    BEGIN
	    ERROR (UPLIT (%ASCIZ'Channel number out of range - INPUT'));
	    AC1 = 0;
	    END
	ELSE
	    AC1 = .CHAN_JFN [.CHAN];

	IF (.AC1 EQL 0)
	THEN
	    BEGIN
	    ERROR (UPLIT (%ASCIZ'Channel not OPEN - INPUT'));
	    RETURN -1
	    END;

!
! The next section of code either returns the character just read for a
!  character mode file or the next byte of a word mode file.
! CHAN_NEXT[.CHAN] is -1 if a new BIN JSYS should be done.
!

	IF (.CHAN_NEXT [.CHAN] LSS 0)
	THEN
	    BEGIN
	    CHAN_CHAR = (IF NOT JSYS_CALL (-1, BIN, AC1, AC2) THEN -1 ELSE .AC2);

	    IF ((.CHAN_MODE [.CHAN] EQL 2) AND (.CHAN_CHAR GEQ 0))
	    THEN
		BEGIN
		CHAN_NEXT [.CHAN] = .CHAN_CHAR<8, 8>;	!Next character
		CHAN_CHAR = .CHAN_CHAR<0, 8>;	!Current Character
		END;

	    END
	ELSE
	    BEGIN				!The second byte of the word
	    CHAN_CHAR = .CHAN_NEXT [.CHAN];	!The character to return
	    CHAN_NEXT [.CHAN] = -1;
	    END;

	END;

    .CHAN_CHAR
    END;					!End of INPUT
GLOBAL ROUTINE OUTPUT (CHANX, OUTWRD) : NOVALUE = 	!Output to a file

!++
! FUNCTIONAL DESCRIPTION:
!
!	Output a byte or word to a file.
!
! FORMAL PARAMETERS:
!
!	CHANX - the channel number
!	OUTWRD - the byte or word to output
!
! IMPLICIT INPUTS:
!
!	NONE
!
! IMPLICIT OUTPUTS:
!
!	NONE
!
! COMPLETION CODES:
!
!	NONE
!
! SIDE EFFECTS:
!
!	NONE
!
!--

    BEGIN

    BIND
	ROUTINE_NAME = UPLIT (%ASCIZ'OUTPUT');

    LOCAL
	CHAN,
	AC1,
	AC2;

!
! Determine whether the channel is for the terminal or a file then
!  process accordingly.
!
    CHAN = .CHANX;

    IF (.CHAN EQL 0)
    THEN
	AC1 = $PRIOU				!For Primary OUTPUT media
    ELSE

	IF ((.CHAN LSS 0) OR (.CHAN GTR 15))
	THEN
	    BEGIN
	    ERROR (UPLIT (%ASCIZ'Channel number out of range - OUTPUT'));
	    AC1 = 0
	    END
	ELSE
	    AC1 = .CHAN_JFN [.CHAN];

    IF (.AC1 EQL 0)
    THEN
	BEGIN
	ERROR (UPLIT (%ASCIZ'Channel not OPEN - OUTPUT'));
	RETURN
	END;

!
! The following code either outputs a character immediately in
!  character mode or waits for two bytes in word mode.
!

    IF ((.CHAN_NEXT [.CHAN] LSS 0) OR (.CHAN EQL 0))
    THEN

	IF (.CHAN_MODE [.CHAN] EQL 2)
	THEN
	    CHAN_NEXT [.CHAN] = .OUTWRD<0, 8>	!First Byte of word
	ELSE
	    BEGIN
	    AC2 = .OUTWRD;
	    JSYS_CALL (0, BOUT, AC1, AC2);
	    END

    ELSE
	BEGIN
	AC2 = ((.OUTWRD<0, 8>)^8) + .CHAN_NEXT [.CHAN];
	JSYS_CALL (0, BOUT, AC1, AC2);
	CHAN_NEXT [.CHAN] = -1;
	END;

    END;					!End of OUTPUT
GLOBAL ROUTINE STOP_PROGRAM : NOVALUE = 	!Terminate execution

!++
! FUNCTIONAL DESCRIPTION:
!
!	Terminates the program. Usually used to stop program when some
!	abnormal condition occurs.
!
! FORMAL PARAMETERS:
!
!	NONE
!
! IMPLICIT INPUTS:
!
!	NONE
!
! IMPLICIT OUTPUTS:
!
!	NONE
!
! COMPLETION CODES:
!
!	NONE
!
! SIDE EFFECTS:
!
!	The program is halted.
!
!--

    BEGIN

    BIND
	ROUTINE_NAME = UPLIT (%ASCIZ'STOP_PROGRAM');

    JSYS_CALL (0, HALTF);
    END;					!of RESET_ALL

END						!End of module

ELUDOM
! Local Modes:
! Comment Column:36
! Comment Start:!
! Auto Save Mode:2
! Mode:Fundamental
! End: