Google
 

Trailing-Edge - PDP-10 Archives - BB-J939B-BM - binary/ezio20.b36
There are 3 other files named ezio20.b36 in the archive. Click here to see a list.
MODULE EZIO20 (					! Provides basic file I/O to BLISS-36 programs	
						!  running on TOPS-20
		ENVIRONMENT (BLISS36C_OTS) ,
		LINKAGE (BLISS36C) ,
		IDENT = '7'
		) =
!<BLF/MACRO>
!<BLF/UPPERCASE_KEY>
!<BLF/LOWERCASE_USER>
!<BLF/WIDTH:80>
BEGIN
!
!			  COPYRIGHT (c) 1978 BY
!	      DIGITAL EQUIPMENT CORPORATION, MAYNARD, MASS.
!
! 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.
!

!++
! Functional Description:
!	This module declares the routines to Open, Close, Read and
! write files.  The functionality provided is very basic and is intended
! only to be transportable and easy to use.
!	Its counterparts on other Operating Systems are EZIO10 (TOPS-10),
! EZIO11 (RMS-11), EZIO32 (RMS-32), and EZIOFC (FCS-11).
!	This module has a counter part (EZIO20) that runs under BLS36C in
! the field. This module is setup for the BLS36C calling sequence, and uses
! the BLISS-36 compiler BUILTIN JSYS. It is very dependent upon the BLISS-36
! compiler (it won't compile under BLS36C).
!
! Environment: User mode
!
! Author: Bruce Dawson, Creation Date: 16-Nov-77
!
! Modified by:
!	Who, date - resultant version
! edit - explaination
!	Bruce Dawson, November 21, 1977 - still version 1
! 1	- Problems when outputting a string of length 0. FILOUT affected.
! 2	- FILIN: Cleaned up ACx usage after RDTTY.
!	Bruce Dawson, 30-June-78 - version 1A
! 3	- Declarations: SUCCESS changed from -1 to 1
!	Bruce Dawson, 5-July-78
! 4	- FILIN: Stand-alone LF messing things up. Created the RETURN_SIZE
!		macro.
! 5	- FILIN: RDTTY breaks on first character instead of waiting for next
!		(possibly editing) character. Gave it 3 characters minimum.
! 6	- FILIN: If the last line of the file did not have CRLF after it,
!		then it was not properly returned. It is now.
! 7	- Module Prolog, FILOPN, FILIN, FILOUT. Added (for 2nd time) the
!		MAXCHANS parameter.
!--

!
! Table of Contents:
!

FORWARD ROUTINE
    filopn,					! Opens a file on a channel.
    filcls,				! Closes a file opened on a channel.
    filin,					! Reads from a channel.
    filout;					! Writes onto a channel.

!
! Macros:
!

MACRO
    fld$who =
	0, 18, 18, 0 %,				!  Who failed.
    fld$cod =
	0, 0, 18, 0 %,				! ERROR CODE.
    fld$lh =
	0, 18, 18, 0 %,
    fld$rh =
	0, 0, 18, 0 %,
    fld$of_bsz =
	0, 30, 6, 0 %,				! Byte size
    fld$of_mod =
	0, 26, 3, 0 %,				! Data mode.
    fld$of_rd =
	0, 16, 1, 0 %,				! Read access
    fld$of_wr =
	0, 15, 1, 0 %,				! Write access
    fld$of_ex =
	0, 14, 1, 0 %,				! Execute access
    fld$of_app =
	0, 13, 1, 0 %,				! Append access
    fld$gj_sht =
	0, 18, 1, 0 %,
    fld$gj_new =
	0, 34, 1, 0 %,
    fld$gj_fou =
	0, 35, 1, 0 %,
    fld$gj_old =
	0, 33, 1, 0 %,
    fld$rd_bel =
	0, 32, 1, 0 %,				! Break at EOL
    fld$gs_eof =
	0, 27, 1, 0 %,				! Read past EOF.
    fld$rd_btm =
	0, 23, 1, 0 %;			! Break character terminated input.

MACRO 						! CROCKS
    jsys_crock (typ, fun, a1, a2, a3, a4) =
	BEGIN

	REGISTER
	    rac1 = 1,
	    rac2 = 2,
	    rac3 = 3,
	    rac4 = 4;

	BUILTIN
	    jsys;

	LOCAL
	    val;

	%IF NOT %NULL (a1)
	%THEN
	    rac1 = .a1;
	%FI

	%IF NOT %NULL (a2)
	%THEN
	    rac2 = .a2;
	%FI

	%IF NOT %NULL (a3)
	%THEN
	    rac3 = .a3;
	%FI

	%IF NOT %NULL (a4)
	%THEN
	    rac4 = .a4;
	%FI

	val = jsys (typ, fun, rac1, rac2, rac3, rac4);

	%IF NOT %NULL (a1)
	%THEN

	    %IF %DECLARED (a1)
	    %THEN
		a1 = .rac1;
	    %FI

	%FI

	%IF NOT %NULL (a2)
	%THEN

	    %IF %DECLARED (a2)
	    %THEN
		a2 = .rac2;
	    %FI

	%FI

	%IF NOT %NULL (a3)
	%THEN

	    %IF %DECLARED (a3)
	    %THEN
		a3 = .rac3;
	    %FI

	%FI

	%IF NOT %NULL (a4)
	%THEN

	    %IF %DECLARED (a4)
	    %THEN
		a4 = .rac4;
	    %FI

	%FI

	.val
	END %;

!
! Equated Symbols:
!

LITERAL
    maxchans = 3,		! Maximum number of channels (biased at 0)
    success = 1,		! Return to call successfully completed.
    failure = 0,			! Return to caller after an error.
    myspacesize = 1000;		! Number of bytes in my buffer

LITERAL 					! JSYS definitions
    gtjfn = %O'20',				! Get a JFN
    openf = %O'21',				! Open a file
    closf = %O'22',				! Close a JFN
    gtsts = %O'24',				! Get JFN status
    rdtty = %O'523',				! Read from TTY
    sin = %O'52',				! String input.
    sout = %O'53',				! String output
    psout = %O'76';				! String output to TTY:

!
! OWN storage
!

OWN
    chan_tab : VECTOR [maxchans] INITIAL(REP maxchans OF (0)),	
				! Table of JFNs for each channel opened.
    error : BLOCK [1],		! Has error on a JSYS failure. Not of use yet,
    crlf : VECTOR [CH$ALLOCATION (2)] INITIAL(%CHAR (%O'15', %O'12')),	
						! A string with CRLF in it.
    space : VECTOR [CH$ALLOCATION(myspacesize)];			! Workspace.
GLOBAL ROUTINE filopn (channel, num_chars, filespec, direction) = 	
						! Open a file

!++
! Functional Description:
!	This routine Opens a file for either Input or Output on the
! specified channel. If it fails (syntax error in file name, non-
! existant file on input, etc...), the routine returns 0 (False).
! Otherwise it returns a nonzero value.
!
! Formal Parameters:
! CHANNEL: A number between -1 and 2. Subsequent I/O to the file
!	must specify this channel number. (-1 means the TTY:)
! NUM_CHARS: The number of ASCII bytes in the filename.
! FILESPEC: A BLISS-36 character pointer pointing to the first
!	character of the filename.
! DIRECTION: If 1 then the file will be opened for WRITE access.
!	Otherwise it will be opened for reading.
!
! Implicit Inputs:
! CHAN_TAB: Contains the JFN for the respective channel.
!
! Implicit Outputs:
! CHAN_TAB: If a file was successfully opened, then contains the
!	JFN for that file on this channel.
! ERROR: If any JSYS fails, then this contains the failing JSYS
!	and the error returned by the JSYS.
!
! Completion Codes:
!  0 = Could not open file.
! #0 = File opened.
!
! Side effects:
!	OWN variable SPACE is used to hold the filespec in ASCIZ
! format.
!--

    BEGIN

    LOCAL
	ac1 : BLOCK [1],			! Parameter for JSYS
	ac2 : BLOCK [1];			! Parameter for JSYS

    IF .channel GTR maxchans - 1
    THEN RETURN failure;

    IF .channel EQL -1
    THEN 		! TTY I/O always works, therefore always return
	RETURN success;

    IF .chan_tab [.channel] NEQ 0
    THEN 					! Channel already opened.
	BEGIN
	error = 0;			! Indicate "nonsense call" error.
	RETURN failure;				! Chastise caller.
	END;

    CH$MOVE (.num_chars, .filespec, CH$PTR (space));	
				! Move caller's filespec to my work space
    CH$WCHAR (0, CH$PLUS (CH$PTR (space), .num_chars));	! Make it ASCIZ
    ac1 = 0;					! Clear AC1 first
    ac1 [fld$gj_sht] = 1;			! Short form for defaulting

    IF .direction EQL 1				! Writing
    THEN
	BEGIN
	ac1 [fld$gj_fou] = 1;			! New generation number
	ac1 [fld$gj_new] = 1;
	END
    ELSE
	BEGIN
	ac1 [fld$gj_old] = 1;
	END;

    ac2 = CH$PTR (space);

    IF jsys_crock (1, gtjfn, ac1, ac2)
    THEN
	chan_tab [.channel] = .ac1 [fld$rh]	
			! Set channel to open on successful monitor return
    ELSE
	BEGIN					! JSYS failed.
	error [fld$who] = gtjfn;
	error [fld$cod] = .ac1;
	RETURN failure;				! Tell caller.
	END;

    ac1 = .chan_tab [.channel];			! Get JFN.
    ac2 = 0;
    ac2 [fld$of_bsz] = 7;		! Byte size is 7 bits for ASCII
    ac2 [fld$of_mod] = 0;			! Mode is zero for text file.
! Set proper bits for reading or writing.

    IF .direction EQL 1
    THEN
	ac2 [fld$of_wr] = 1
    ELSE
	ac2 [fld$of_rd] = 1;

    IF jsys_crock (1, openf, ac1, ac2)
    THEN
	RETURN success	! OPENF worked. Channel is now available for use.
    ELSE
	BEGIN					! OPENF failed.
	error [fld$who] = openf;
	error [fld$cod] = .ac1;
	RETURN failure;				! Tell user.
	END;

    END;
GLOBAL ROUTINE filcls (channel) = 	
				! Close the file on the specified channel.

!++
! Functional Description:
!	This routine closes the file opened on the specified channel.
!
! Formal Parameters:
! CHANNEL: A number between -1 and 2 specifing the channel to close.
!
! Implicit Inputs:
! CHAN_TAB: If the respective entry for the channel already has a
!	zero, then this indicates that the channel has already been
!	closed (or never opened). An error return is given to tell
!	the user that the call was nonsense.
!
! Implicit Outputs:
! CHAN_TAB: The respective entry for the channel is made zero to
!	 indicate the channel is closed.
! ERROR: If an error was encountered, then this is changed to indicate
!	who caused the error, and what the error was.
!
! Completion Codes:
!  0 = Nonsense call or JSYS failure.
! #0 = Successful return.
!
! Side effects: None
!--

!
    BEGIN

    LOCAL
	ac1 : BLOCK [1];			! Parameter for JSYS

    IF .channel GTR maxchans - 1
    THEN RETURN failure;

    IF .channel EQL -1
    THEN
	RETURN success;				! Don't worry about TTY:

    IF .chan_tab [.channel] EQL 0
    THEN
	BEGIN					! Nonsense call.
	error = 0;				! Inform caller of such.
	RETURN failure;
	END;

    ac1 = .chan_tab [.channel];			! Get JFN

    IF NOT jsys_crock (1, closf, ac1)
    THEN
	BEGIN					! CLOSF JSYS failed.
	error [fld$who] = closf;		! Indicate which JSYS failed;
	error [fld$cod] = .ac1;			! And save error code
	RETURN failure;				! Inform caller.
	END;

    chan_tab [.channel] = 0;
    RETURN success;
    END;
GLOBAL ROUTINE filin (channel, bufsiz, pointer) = 	
						! Read from the channel.

!++
! Functional Description:
!	This routine reads data from the specified channel and
! deposits it in the specified string. Data transfer stops if
! CRLF is encountered or if the string is filled.
!	Returns the number of characters transefered to the string,
! (0 characters means a null line), or -1 for EOF.
!	The CRLF is trimmed from the returned string. Line numbers are
!	ignored (won't appear in the string).
!
! Formal Parameters:
! CHANNEL: A number between -1 and 2 specifiing the channel from
!	which to read from.
! BUFSIZ: The maximum number of characters to transfer to the string.
! POINTER: A BLISS-36 character pointer pointing to the string to
!	which data is to be transfered.
!
! Implicit Inputs:
! CHAN_TAB: Used to determine the JFN for the respective channel.
!
! Implicit Outputs:
! ERROR: If an error occurs, then ERROR si changed to indicate who
!	caused the error and what the error was.
!
! Condition Codes:
! Routine Value:
! -1 if EOF encountered.
! -2 if an error happened.
! >=0 if data was successfully transfered.
!
! Side Effects: None
!--

    BEGIN

    LOCAL
	ac1 : BLOCK [1],			! Parameter for JSYS
	ac2 : BLOCK [1],			! Parameter for JSYS
	ac3 : BLOCK [1],			! Parameter for JSYS
	ac4 : BLOCK [1];			! Parameter for JSYS

    LOCAL
	len,				! Number of characters left in buffer
	updptr;				! Updated string pointer from SIN

    MACRO
	return_size =				! Return the size of the string
	    IF CH$RCHAR (CH$PLUS (.updptr, -2)) LEQ %O'15' 
		AND CH$RCHAR (CH$PLUS (.updptr, -2)) GEQ %O'13'
				! See if line terminator or full buffer
	    THEN
		RETURN MAX (.bufsiz - .len - 2, 0)	
			! Effectively remove CRLF by returning shorter length
	    ELSE
		IF .len EQL 0
		THEN RETURN .bufsiz		! Full buffer
! WARNING*** This MUST be the last line of the macro, and can't have a ";"
		ELSE RETURN .bufsiz - .len - 1	! Everything up to LF
	    %;


    IF .channel GTR maxchans - 1
    THEN RETURN failure;

    IF .channel EQL -1
    THEN 					! Read from TTY:
	BEGIN
	ac1 = CH$PTR (space);			! Point to buffer
	ac2 = 0;
	ac2 [fld$rd_bel] = 1;			! Set Break On End Of Line
	ac2 [fld$rh] = MAX (.bufsiz+2, myspacesize);	! Set max size of string
	ac3 = 0;				! No prompting

	IF jsys_crock (1, rdtty, ac1, ac2, ac3)	
					! Use RDTTY so user can edit input.
	THEN
	    BEGIN
!
! Return length of input string.
!
	    ROUTINE acutalsize (len, updptr, bufsiz) =
		return_size;

	    LOCAL
		len;

	    len = acutalsize (.ac2[fld$rh], .ac1, myspacesize);
	    CH$MOVE (.len, CH$PTR (space), .pointer);
	    RETURN .len;

	    END
	ELSE
	    BEGIN				! RDTTY Failed.
	    error [fld$who] = rdtty;
	    error [fld$cod] = .ac1;
	    RETURN -2;				! Inform caller.
	    END;

	END;

!
! Got here if NOT reading from TTY:.
!
    ac1 = .chan_tab [.channel];			! Get JFN
    ac2 = .pointer;				! Get input buffer pointer.
    ac3 = .bufsiz;				! Get max. buffer size
    ac4 = %O'12';				! Break on <LF>

    IF jsys_crock (-1, sin, ac1, ac2, ac3, ac4)
    THEN
	BEGIN
	len = .AC3;
	updptr = .AC2;
	return_size;
	END

    ELSE
	BEGIN				! SIN JSYS failed, find out why.
	len = .ac3;			! Preserve returned length of string
	error [fld$who] = sin;			! Preset who failed.
	error [fld$cod] = .ac1;			! Preset why it failed.
	ac1 = .chan_tab [.channel];		! Get JFN
	ac2 = 0;
	jsys_crock (0, gtsts, ac1, ac2);	
					! See what monitor thinks of file.

	IF .ac2 [fld$gs_eof]
	THEN
	    IF .len EQL .bufsiz		! See if nothing actually read
	    THEN RETURN -1
	    ELSE return_size + 1
	ELSE RETURN -2;				! Indicate error occurred.

	END;

    END;
GLOBAL ROUTINE filout (channel, num_chars, pointer) = 	
						! Write data on a channel.

!++
! Functional Description:
!	This routine writes data from the specified string to the
! specified channel. A CRLF is appended to the data after output.
!	Will return an error (zero) if NUM_CHARS is less than zero,
! or if a JSYS failed.
!
! Formal Parameters:
! CHANNEL: A number between -1 and 2 that specifies the channel which
!	output is to occur on.
! NUM_CHARS: The number of characters in the string.
! POINTER: A BLISS-36 character pointer pointing to the string
!	from which data is transfered.
!
! Implicit Inputs:
! CHAN_TAB: Used to determine the JFN for the channel.
!
! Implicit Outputs:
! ERROR: If an error occurs, then this will contain who caused the
!	error, and the error code.
!
! Completion Codes:
!  0 = Error occured.
! #0 = Data transfer completed without errors.
!
! Side Effects: None
!--

    BEGIN

    LOCAL
	ac1 : BLOCK [1],			! Parameter to JSYS
	ac2 : BLOCK [1],			! Parameter to JSYS
	ac3 : BLOCK [1],			! Parameter to JSYS
	ac4 : BLOCK [1];			! Parameter to JSYS

    IF .channel GTR maxchans - 1
    THEN RETURN failure;

    IF .num_chars LSS 0				! Nonsense call check.
    THEN
	RETURN failure;				! Chastise caller.

    IF .channel EQL -1
    THEN
	BEGIN					! Use PSOUT for TTY.

	IF .num_chars GTR 0
	THEN
	    BEGIN
	    CH$MOVE (.num_chars, .pointer, CH$PTR (space));	
					! Move his string to my work space
	    CH$WCHAR (%O'15', CH$PLUS (CH$PTR (space), .num_chars));	
						! Append CR
	    CH$WCHAR (%O'12', CH$PLUS (CH$PTR (space), .num_chars + 1));	
						! And LF
	    CH$WCHAR (0, CH$PLUS (CH$PTR (space), .num_chars + 2));	
						! Make the whole thing ASCIZ.
	    ac1 = CH$PTR (space);		! Set up for monitor call.
	    END
	ELSE
	    ac1 = CH$PTR (crlf);

	IF NOT jsys_crock (-1, psout, ac1)
	THEN
	    BEGIN				! Failed for some reason
	    error [fld$cod] = psout;		! Record who failed.
	    error [fld$who] = .ac1;		! Record why.
	    RETURN failure;			! Inform caller
	    END
	ELSE
	    RETURN success;			! Done, return to caller.

	END;

!
! Got here if NOT writing to TTY:.
!

    IF .num_chars GTR 0
    THEN
	BEGIN
	ac1 = .chan_tab [.channel];		! Get JFN
	ac2 = .pointer;				! Get string pointer
	ac3 = -.num_chars;		! Get negative number chars in string
	ac4 = 0;				! Don't break output.

	IF NOT jsys_crock (-1, sout, ac1, ac2, ac3, ac4)
	THEN
	    BEGIN				! Indicate error
	    error [fld$who] = sout;
	    error [fld$cod] = .ac1;
	    RETURN failure;
	    END;

	END;

    ac1 = .chan_tab [.channel];
    ac2 = CH$PTR (crlf);
    ac3 = -2;
    ac4 = 0;

    IF jsys_crock (-1, sout, ac1, ac2, ac3, ac4)
    THEN
	RETURN success;

!
! Got here if an error occured above.
!
    error [fld$who] = sout;
    error [fld$cod] = .ac1;
    RETURN failure;
    END;

END

ELUDOM