Google
 

Trailing-Edge - PDP-10 Archives - BB-R595B-SM_11-9-85 - mcb/tkb36/cmds.bli
There are 2 other files named cmds.bli in the archive. Click here to see a list.
!<REL4A.TKB-VNP>CMDS.BLI.7,  3-Dec-79 14:25:36, Edit by SROBINSON
MODULE CMDS (					! COMMAND SCANNER
		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
!
! ABSTRACT:
!
!
! THIS IS THE COMMAND SCANNER FOR THE TASK BUILDER.
!
!
! ENVIRONMENT: TOPS-20
!
! AUTHOR: J. SAUTER, CREATION DATE: 14-DEC-77
!
! MODIFIED BY:
!
!	Scott G. Robinson, 15-FEB-79 : VERSION X0.1-2A
!	- Make calls to CMDLIN include the prompt
!-----------------------------------------------------------------------
!
!	Scott G. Robinson, 3-DEC-79 : Version X2.0
!	- Setup for DECnet-10 compatibility
!
!	, : VERSION
! 01	-
!--

!<BLF/PAGE>
!
! TABLE OF CONTENTS:
!

FORWARD ROUTINE
    UPPER_CASE,					!CONVERT LOWER CASE TO UPPER
    SCN_FILE_NAME,				!SCAN A FILE NAME
    SCN_SWITCH,					!SCAN A SWITCH
    CMDLIN,					!PROCESS A COMMAND LINE (GLOBAL)
    GET_SW,					!GET SWITCH AND VALUE (GLOBAL)
    SEL_SWITCH;					! SUBROUTINE USED BY GET_SW

!
! INCLUDE FILES:
!

LIBRARY 'TKBLIB';

!REQUIRE 'BLOCKH.REQ';				!PREPARE TO DEFINE STORAGE BLOCKS
!REQUIRE 'FILE.REQ';				!DEFINE FILE BLOCK
!REQUIRE 'FILSW.REQ';				!DEFINE FILE SWITCH BLOCK
!REQUIRE 'BLOCKT.REQ';				!END OF DEFINING BLOCKS
!
! MACROS:
!
!	NONE
!
! EQUATED SYMBOLS:
!
!	NONE
!
! OWN STORAGE:
!
!	NONE
!
! EXTERNAL REFERENCES:
!

EXTERNAL ROUTINE
    BLD_CHAIN,					!BUILD A MULTIPLE-POINTER LIST
    CLOSE : NOVALUE,				!CLOSE A FILE
    OPEN,					!OPEN A FILE
    ERRMSG : NOVALUE,				!PRINT ERROR MESSAGE
    ERROR,					!ANNOUNCE A PROGRAMMING ERROR
    FND_CHAIN,					!FIND A BLOCK IN A CHAIN
    FREBLK : NOVALUE,				!RETURN A BLOCK TO THE FREE LIST
    GETBLK,					!GET A BLOCK FROM THE FREE LIST
    INPUT,					!READ FROM I/O DEVICE
    PCRLF : NOVALUE,				!PRINT CRLF
    OUTSTR : NOVALUE;				!PRINT A STRING
ROUTINE UPPER_CASE (CHAR) = 			!CONVERT LC TO UC

!++
! FUNCTIONAL DESCRIPTION:
!
!
!
!	ROUTINE TO CONVERT LOWER CASE CHARACTERS TO UPPER CASE
!	ALL CHARACTERS FROM LOWER CASE "A" TO LOWER CASE "Z"
!	GET OCTAL 40 SUBTRACTED FROM THEM.  ALL OTHER CHARACTERS
!	ARE RETURNED UNCHANGED.
!
!
! FORMAL PARAMETERS:
!
!	CHAR - THE CHARACTER TO BE CONVERTED
!
! IMPLICIT INPUTS:
!
!	NONE
!
! IMPLICIT OUTPUTS:
!
!	NONE
!
! ROUTINE VALUE:
!
!	THE CHARACTER, CONVERTED TO UPPER CASE IF NECESSARY
!
! SIDE EFFECTS
!
!	NONE
!
!--

    BEGIN

    SELECTONE .CHAR OF
	SET

	[%C'a' TO %C'z'] :
	    .CHAR - %O'40';

	[OTHERWISE] :
	    .CHAR;
	TES

    END;
ROUTINE SCN_FILE_NAME (PTR) = 			! SCAN FILE NAME

!++
! FUNCTIONAL DESCRIPTION:
!
!	SCAN A FILE NAME.  STOP ON PROPER DELIMETER.
!
! FORMAL PARAMETERS:
!
!	PTR - POINTER TO TEXT; GETS UPDATED.
!
! IMPLICIT INPUTS:
!
!	THE TEXT POINTED TO IS READ
!
! IMPLICIT OUTPUTS:
!
!	NONE
!
! ROUTINE VALUE:
!
!	POINTER TO FILE BLOCK, OR 0 IF OUT OF STORAGE.
!
! SIDE EFFECTS
!
!	OBTAINS STORAGE FROM THE FREE LIST
!
!--

    BEGIN

    LOCAL
	CHAR,
	FILE_PTR : REF FILE_BLOCK,
	FIL_N_CTR,
	FIL_N_PTR,
	SCAN_DONE;

!

    IF ((FILE_PTR = GETBLK (FILE_TYP, FILE_LEN)) EQL 0)
    THEN
	BEGIN
	ERRMSG (0, 1, UPLIT (%ASCIZ'SCAN_FILE_NAME'), 0, 0, 0, 0);
	0
	END
    ELSE
	BEGIN
	FIL_N_PTR = CH$PTR (FILE_PTR [FILE_NAME], -1);
	SCAN_DONE = 0;
	FIL_N_CTR = 0;

	DO
	    BEGIN
	    CHAR = UPPER_CASE (CH$A_RCHAR (.PTR));

	    CASE .CHAR FROM 0 TO 127 OF
		SET

		[%C'A' TO %C'Z', %C'0' TO %C'9', %C'.', %C'<', %C'>', %C'[', %C']', %C':', %C'-'] :
		    BEGIN			!VALID CHAR IN FILE NAME

		    IF (.FIL_N_CTR LSS (LEN_FILE_STRING - 1))
		    THEN
			BEGIN
			CH$A_WCHAR (.CHAR, FIL_N_PTR);
			FIL_N_CTR = .FIL_N_CTR + 1;
			END
		    ELSE
			SCAN_DONE = -1;

		    END;

		[%C',', %C'/', %C'=', 0] :
		    BEGIN			!VALID DELIMETER
		    SCAN_DONE = 1;
		    .PTR = CH$PLUS (..PTR, -1);
		    END;

		[INRANGE] :
		    BEGIN
		    SCAN_DONE = -1;
		    CH$A_WCHAR (.CHAR, FIL_N_PTR);
		    END;
		TES;

	    END
	UNTIL (.SCAN_DONE NEQ 0);

	CH$A_WCHAR (0, FIL_N_PTR);		!TERMINATE FILE NAME

	IF (.SCAN_DONE LSS 0)
	THEN
	    ERRMSG (0, 2, UPLIT (%ASCIZ'SCAN_FILE_NAME'), FILE_PTR [FILE_NAME], 0, 0,
		0);

	.FILE_PTR				!RETURN POINTER TO FILE BLOCK
	END					!GOT STORAGE
    END;					!ROUTINE SCN_FIL_NAME (SCAN_FILE_NAME)
ROUTINE SCN_SWITCH (PTR) = 			! SCAN A SWITCH

!++
! FUNCTIONAL DESCRIPTION:
!
!	SCAN A SWITCH WITH OPTIONAL VALUE
!
! FORMAL PARAMETERS:
!
!	PTR - POINTER TO TEXT; GETS UPDATED.
!	 INITIALLY POINTS RIGHT AFTER THE "/".
!
! IMPLICIT INPUTS:
!
!	THE TEXT POINTED TO IS READ
!
! IMPLICIT OUTPUTS:
!
!	NONE
!
! ROUTINE VALUE:
!
!	POINTER TO LIST OF SWITCH BLOCKS, OR 0 IF OUT OF STORAGE.
!
! SIDE EFFECTS
!
!	OBTAINS STORAGE FROM THE FREE LIST.
!	THE POINTER IS LEFT POINTING TO THE FIRST CHAR AFTER THE SWITCH
!
!--

    BEGIN

    LOCAL
	CHAR,
	DEC_VAL,
	OCT_BAD,
	OCT_VAL,
	SCAN_DONE,
	SW_PTR : REF FILSW_BLOCK,
	VALUE_TEXT : VECTOR [CH$ALLOCATION (LEN_FSW_TEXT)],
	VAL_TYPE,
	WORD_CTR,
	WORD_DONE,
	WORD_PTR;

    SCAN_DONE = 0;

    IF ((SW_PTR = GETBLK (FILSW_TYP, FILSW_LEN)) EQL 0)
    THEN
	BEGIN
	ERRMSG (0, 1, UPLIT (%ASCIZ'SCAN_SWITCHES'), 0, 0, 0, 0);
	SCAN_DONE = -1;
	END;

    IF (.SCAN_DONE EQL 0)
    THEN
	BEGIN					!SETUPS ARE OK
	WORD_DONE = 0;
	WORD_CTR = 0;
	WORD_PTR = CH$PTR (SW_PTR [FSW_NAME], -1);

	WHILE (.WORD_DONE EQL 0) DO
	    BEGIN
	    CHAR = UPPER_CASE (CH$A_RCHAR (.PTR));

	    SELECT .CHAR OF
		SET

		[%C'A' TO %C'Z', %C'0' TO %C'9', %C'.', %C'-'] :
		    BEGIN

		    IF (.WORD_CTR LSS (LEN_FSW_NAME - 1))
		    THEN
			BEGIN
			CH$A_WCHAR (.CHAR, WORD_PTR);
			WORD_CTR = .WORD_CTR + 1;
			END
		    ELSE
			BEGIN
			SCAN_DONE = -1;
			WORD_DONE = -1;
			END;

		    END;

		[%C'/', %C',', %C'=', 0] :
		    BEGIN
		    SCAN_DONE = 1;
		    .PTR = CH$PLUS (..PTR, -1);
		    END;

		[%C':', %C'/', %C',', %C'=', 0] :
		    BEGIN
		    WORD_DONE = 1;
		    END;

		[OTHERWISE] :
		    BEGIN
		    SCAN_DONE = -1;		!INVALID CHARACTER
		    WORD_DONE = -1;
		    END;
		TES;

	    END;				!SCAN OF WORD

	IF (.SCAN_DONE EQL 0)
	THEN
	    BEGIN				!WE HAVE A VALUE FOR THIS SWITCH
	    WORD_DONE = 0;
	    CHAR = CH$A_RCHAR (.PTR);

	    SELECTONE UPPER_CASE (.CHAR) OF
		SET

		[%C'0' TO %C'9'] :
		    BEGIN			!NUMERIC
		    DEC_VAL = 0;
		    OCT_VAL = 0;
		    OCT_BAD = 0;
		    VAL_TYPE = 1;		!ASSUME OCTAL NUMBER

		    WHILE (.WORD_DONE EQL 0) DO
			BEGIN

			SELECT .CHAR OF
			    SET

			    [%C'0' TO %C'7'] :
				OCT_VAL = (.OCT_VAL*8) + (.CHAR - %C'0');

			    [%C'0' TO %C'9'] :
				DEC_VAL = (.DEC_VAL*10) + (.CHAR - %C'0');

			    [%C'8' TO %C'9'] :
				OCT_BAD = 1;

			    [%C'.'] :
				BEGIN
				VAL_TYPE = 2;	!MUST BE DECIMAL NUMBER
				WORD_DONE = 1;
				SCAN_DONE = 1;
				END;

			    [%C'/', %C',', %C'=', 0] :
				BEGIN
				SCAN_DONE = 1;
				WORD_DONE = 1;
				.PTR = CH$PLUS (..PTR, -1);
				END;

			    [OTHERWISE] :
				BEGIN
				SCAN_DONE = -1;
				WORD_DONE = -1;
				END;
			    TES;

			IF (.WORD_DONE EQL 0) THEN CHAR = CH$A_RCHAR (.PTR);

			END;

		    END;			!NUMERIC

		[%C'A' TO %C'Z', %C'$', %C'.'] :
		    BEGIN			!TEXT
		    WORD_CTR = 0;
		    WORD_PTR = CH$PTR (VALUE_TEXT, -1);
		    VAL_TYPE = 3;

		    WHILE (.WORD_DONE EQL 0) DO
			BEGIN

			SELECTONE UPPER_CASE (.CHAR) OF
			    SET

			    [%C'A' TO %C'Z', %C'0' TO %C'9', %C'$', %C'.'] :
				BEGIN

				IF (.WORD_CTR LSS (LEN_FSW_TEXT - 1))
				THEN
				    BEGIN
				    CH$A_WCHAR (.CHAR, WORD_PTR);
				    WORD_CTR = .WORD_CTR + 1;
				    END
				ELSE
				    BEGIN
				    SCAN_DONE = -1;
				    WORD_DONE = -1;
				    END;

				END;

			    [%C'/', %C',', %C'=', 0] :
				BEGIN
				SCAN_DONE = 1;
				WORD_DONE = 1;
				.PTR = CH$PLUS (..PTR, -1);
				END;

			    [OTHERWISE] :
				BEGIN
				SCAN_DONE = -1;
				WORD_DONE = -1;
				END;
			    TES;

			IF (.WORD_DONE EQL 0) THEN CHAR = CH$A_RCHAR (.PTR);

			END;

		    END;			!TEXT

		[OTHERWISE] :
		    BEGIN
		    SCAN_DONE = -1;
		    WORD_DONE = -1;
		    END;
		TES;

!

	    IF (.WORD_DONE GTR 0)
	    THEN
		BEGIN

		CASE .VAL_TYPE FROM 1 TO 3 OF
		    SET

		    [1] :
			BEGIN			!OCTAL NUMBER

			IF (.OCT_BAD NEQ 0)
			THEN
			    SCAN_DONE = -1
			ELSE
			    BEGIN
			    SW_PTR [FSW_VAL] = .OCT_VAL;
			    SW_PTR [FSW_VAL_PRES] = 1;
			    END;

			END;

		    [2] :
			BEGIN			!DECIMAL NUMBER
			SW_PTR [FSW_VAL] = .DEC_VAL;
			SW_PTR [FSW_VAL_PRES] = 1;
			END;

		    [3] :
			BEGIN			!TEXT
			CH$MOVE (.WORD_CTR, CH$PTR (VALUE_TEXT), CH$PTR (SW_PTR [FSW_TEXT]));
			SW_PTR [FSW_TEXT_PRES] = 1;
			END;
		    TES;

		END;				!WORD_CTR GTR 0

	    END					!VALUE FOR THIS SWITCH
	END;					!SETUPS ARE OK

    IF (.SCAN_DONE LEQ 0)
    THEN
	BEGIN

	IF (.SW_PTR NEQ 0) THEN FREBLK (.SW_PTR);

	0
	END
    ELSE
	BEGIN
	.SW_PTR
	END

    END;					!ROUTINE SCN_SWITCH (SCAN_SWITCHES)
GLOBAL ROUTINE CMDLIN (CHANNEL, UP_FILE, PROMPT) = 	! SCAN A COMMAND LINE

!++
! FUNCTIONAL DESCRIPTION:
!
!	ROUTINE TO PROCESS A COMMAND LINE
!	HANDLES INDIRECTION AND SWITCHES
!
! FORMAL PARAMETERS:
!
!	CHANNEL - FIRST CHANNEL OVER WHICH TO GET INPUT
!	UP_FILE - POINTER TO PREVIOUS FILE BLOCK (ROOT IF CHANNEL = 0)
!	PROMPT - POINTER TO PROMPT STRING (ISSUED TO TERMINAL)
!
! IMPLICIT INPUTS:
!
!	DATA FROM THE INDICATED CHANNEL, AND FROM SPECIFIED FILES
!
! IMPLICIT OUTPUTS:
!
!	ADDS FILES TO THE DATA STRUCTURE POINTED TO BY UP_FILE
!
! ROUTINE VALUE:
!
!	0 = SYNTAX ERROR, 1 = SUCCESS.
!
! SIDE EFFECTS
!
!	GETS STORAGE FROM FREE LIST
!	READS FROM SPECIFIED I/O CHANNEL, AND FROM
!	 FILES AS SPECIFIED IN THE COMMAND STRING
!
!--

    BEGIN

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

    LOCAL
	CHAN,
	CHAR,
	FILE_PTR : REF FILE_BLOCK,
	FIRST_FILE : REF FILE_BLOCK,
	HIGHER_FILE : REF FILE_BLOCK,
	IND_FILE_PTR : VECTOR [5],		!POINTS TO FILE BLOCKS
	NXT_FILE_PTR : REF FILE_BLOCK,
	SCAN_DONE,
	SEEN_DELIM,
	SEEN_CONT,
	SEEN_EQUAL,
	SWITCH_PTR : REF FILSW_BLOCK,
	TEXT_CTR,
	TEXT_LINE : VECTOR [CH$ALLOCATION (200)],
	TEXT_PTR,
	TMP_FILE_PTR : REF FILE_BLOCK;

    FIRST_FILE = 0;
    SEEN_EQUAL = 0;				!NO '=' YET
    SEEN_CONT = -1;				!PRETEND WE HAVE SEEN CONT MARK
    FILE_PTR = 0;				!NO FILES SEEN YET
    CHAN = .CHANNEL;				!START ON SPECIFIED CHANNEL
    HIGHER_FILE = .UP_FILE;			!START WITH SPECIFIED HIGHER FILE
    IND_FILE_PTR [.CHAN] = .UP_FILE;		!REMEMBER FOR INDIRECT FILES
!
! LOOP HERE TO SCAN CONTINUED LINES
!

    WHILE ((.SEEN_CONT NEQ 0) OR (.CHAN NEQ .CHANNEL)) DO
	BEGIN
	SEEN_CONT = 0;
	SEEN_DELIM = -1;

	IF (.CHAN EQL 0)
	THEN
	    BEGIN
	    OUTSTR (.CHAN, .PROMPT);
	    END;

!
! ABSORB TEXT LINE FROM INPUT DEVICE
!
	TEXT_CTR = 0;
	TEXT_PTR = CH$PTR (TEXT_LINE, -1);

	DO
	    BEGIN
	    CHAR = INPUT (.CHAN);

	    IF (.CHAR LSS 0)
	    THEN
		BEGIN

		IF (.CHAN GTR .CHANNEL)
		THEN
		    BEGIN
		    CLOSE (.CHAN);
		    CHAN = .CHAN - 1;
		    HIGHER_FILE = .IND_FILE_PTR [.CHAN];
		    END
		ELSE
		    ERRMSG (0, 9, ROUTINE_NAME, 0, 0, 0, 0);

		END
	    ELSE

		IF ((.CHAR GEQ %C' ') AND (.TEXT_CTR LSS 200)) THEN CH$A_WCHAR (.CHAR, TEXT_PTR);

	    END
	UNTIL ((.CHAR EQL %O'12') OR ((.CHAR LSS 0) AND (.CHAN EQL .CHANNEL)));

	CH$A_WCHAR (0, TEXT_PTR);		!APPEND NULL TO LINE IMAGE
	TEXT_PTR = CH$PTR (TEXT_LINE, -1);

	IF (.CHAR EQL %O'12')
	THEN
	    SCAN_DONE = 0
	ELSE

	    IF ((.CHAR LSS 0) AND (.CHAN EQL .CHANNEL) AND (SEEN_CONT EQL 0))
	    THEN
		SCAN_DONE = 1
	    ELSE
		SCAN_DONE = -1;

!
! NOW SCAN THE LINE
!

	WHILE (.SCAN_DONE EQL 0) DO
	    BEGIN
	    CHAR = UPPER_CASE (CH$A_RCHAR (TEXT_PTR));

	    SELECTONE .CHAR OF
		SET

		[%C'@'] :
		    BEGIN			!INDIRECT FILE

		    IF (.CHAN GEQ 4)
		    THEN
			ERRMSG (0, 8, ROUTINE_NAME, TEXT_LINE, 0, 0, 0)
		    ELSE

			IF ((IND_FILE_PTR [.CHAN + 1] = SCN_FILE_NAME (TEXT_PTR)) EQL 0)
			THEN
			    ERRMSG (0, 2,
				ROUTINE_NAME, TEXT_LINE, 0, 0, 0)
			ELSE
			    BEGIN
			    TMP_FILE_PTR = .IND_FILE_PTR [.CHAN + 1];
			    TMP_FILE_PTR [FILE_FLAG_IND] = 1;

			    IF (OPEN (.CHAN + 1, TMP_FILE_PTR [FILE_NAME], 1, 0, UPLIT (%ASCIZ'CMD')) NEQ 0)
			    THEN
				BEGIN
				HIGHER_FILE [FILE_DOWN] = BLD_CHAIN (.HIGHER_FILE, .HIGHER_FILE [FILE_DOWN],
				    .TMP_FILE_PTR);
				TMP_FILE_PTR [FILE_HIGH] = .HIGHER_FILE;
				HIGHER_FILE = .TMP_FILE_PTR;
				CHAN = .CHAN + 1;
				END;

			    END;

		    END;

		[%C'A' TO %C'Z', %C'0' TO %C'9'] :
		    BEGIN			!ALPHANUMERIC, MUST START A FILE SPEC

		    IF (.SEEN_DELIM EQL 0)
		    THEN
			BEGIN
			ERRMSG (0, 6, ROUTINE_NAME, TEXT_LINE, 0, 0, 0);
			SCAN_DONE = -1;
			END
		    ELSE
			BEGIN
			TEXT_PTR = CH$PLUS (.TEXT_PTR, -1);
			NXT_FILE_PTR = SCN_FILE_NAME (TEXT_PTR);

			IF (.NXT_FILE_PTR EQL 0)
			THEN
			    SCAN_DONE = -1
			ELSE
			    BEGIN
			    NXT_FILE_PTR [FILE_PREV] = .FILE_PTR;
			    NXT_FILE_PTR [FILE_HIGH] = .HIGHER_FILE;
			    HIGHER_FILE [FILE_DOWN] = BLD_CHAIN (.HIGHER_FILE, .HIGHER_FILE [FILE_DOWN],
				.NXT_FILE_PTR);

			    IF (.FILE_PTR NEQ 0) THEN FILE_PTR [FILE_NEXT] = .NXT_FILE_PTR;

			    FILE_PTR = .NXT_FILE_PTR;

			    IF (.FIRST_FILE EQL 0) THEN FIRST_FILE = .FILE_PTR;

			    IF (.SEEN_EQUAL NEQ 0) THEN FILE_PTR [FILE_FLAG_IN] = 1;

			    SEEN_DELIM = 0;
			    END;

			END;

		    END;

		[%C'/'] :
		    BEGIN			!SWITCHES

		    IF (.SEEN_DELIM NEQ 0)
		    THEN
			ERRMSG (0, 7, ROUTINE_NAME, TEXT_LINE, 0, 0, 0)
		    ELSE
			BEGIN
			SWITCH_PTR = SCN_SWITCH (TEXT_PTR);

			IF (.SWITCH_PTR EQL 0)
			THEN
			    ERRMSG (0, 6, ROUTINE_NAME, TEXT_LINE, 0, 0, 0)
			ELSE
			    BEGIN

			    IF ((FILE_PTR [FILE_SWITCHES] = BLD_CHAIN (.FILE_PTR, .FILE_PTR [FILE_SWITCHES],
				    .SWITCH_PTR)) EQL 0)
			    THEN
				ERRMSG (0, 1, ROUTINE_NAME, 0, 0, 0, 0);

			    END;

			END;

		    END;

		[%C','] :
		    BEGIN			!COMMA, SEPARATES FILE SPECS
		    SEEN_DELIM = -1;
		    END;

		[%C'-'] :
		    BEGIN			!DASH, INDICATES CONTINUATION IN RIGHT CONTEXT

		    IF (SEEN_DELIM NEQ 0) THEN SEEN_CONT = -1;

		    SEEN_DELIM = 0;
		    END;

		[%C'='] :
		    BEGIN			!EQUAL SIGN, SEPATATES OUTPUT FROM INPUT FILES

		    IF ((.SEEN_DELIM NEQ 0) OR (.SEEN_EQUAL NEQ 0))
		    THEN
			BEGIN
			ERRMSG (0, 6, ROUTINE_NAME, TEXT_LINE, 0, 0, 0);
			SCAN_DONE = -1;
			END
		    ELSE
			BEGIN
			SEEN_DELIM = -1;
			SEEN_EQUAL = -1;
!
! MARK ALL FILE SPECS ALREADY SEEN AS BEING TO THE LEFT OF
!  THE EQUAL SIGN.
!
			TMP_FILE_PTR = .FIRST_FILE;

			WHILE (.TMP_FILE_PTR NEQ 0) DO
			    BEGIN
			    TMP_FILE_PTR [FILE_FLAG_OUT] = 1;
			    TMP_FILE_PTR = .TMP_FILE_PTR [FILE_NEXT];
			    END;

			END;

		    END;

		[0] :
		    BEGIN			! END OF LINE
		    SCAN_DONE = 1;
		    END;

		[OTHERWISE] :
		    BEGIN
		    ERRMSG (0, 2, ROUTINE_NAME, TEXT_LINE, 0, 0, 0);
		    SCAN_DONE = -1;
		    END;
		TES;

	    END;				! END OF SCAN LOOP

	END;					! END OF CONTINUATION LINES

    WHILE (.CHAN NEQ .CHANNEL) DO
	BEGIN
	CLOSE (.CHAN);
	CHAN = .CHAN - 1;
	END;

    .SCAN_DONE
    END;

!
GLOBAL ROUTINE GET_SW (FILE_PTR, SWITCH_NAME) = 	!GET SWITCH AND VALUE

!++
! FUNCTIONAL DESCRIPTION:
!
!	GET A SWITCH (ON A FILE) AND ITS VALUE
!
! FORMAL PARAMETERS:
!
!	FILE_PTR - THE FILE BLOCK THAT MAY HAVE THE SPECIFIED SWITCH
!	SWITCH_NAME - NAME OF THE SWITCH, SEVEN CHARACTERS, LAST NULL.
!
! IMPLICIT INPUTS:
!
!	NONE
!
! IMPLICIT OUTPUTS:
!
!	NONE
!
! ROUTINE VALUE:
!
!	POINTER TO THE SWITCH BLOCK, OR 0
!
! SIDE EFFECTS
!
!	NONE
!
!--

    BEGIN

    MAP
	FILE_PTR : REF FILE_BLOCK;

    IF (.FILE_PTR EQL 0) THEN 0 ELSE FND_CHAIN (.FILE_PTR [FILE_SWITCHES], SEL_SWITCH, .SWITCH_NAME)

    END;					!OF GET_SW
ROUTINE SEL_SWITCH (FILSW_PTR, SWITCH_NAME) = 	!SEE IF A SWITCH IS ON A FILE

!++
! FUNCTIONAL DESCRIPTION:
!
!	SEE IF A SWITCH IS ON A FILE.  USED IN CALL TO FND_CHAIN.
!
! FORMAL PARAMETERS:
!
!	FILSW_PTR - POINTER TO A FILE SWITCH TO TEST
!	SWITCH_NAME - POINTER TO NAME OF SWITCH TO LOOK FOR
!
! IMPLICIT INPUTS:
!
!	NONE
!
! IMPLICIT OUTPUTS:
!
!	NONE
!
! ROUTINE VALUE:
!
!	0 IF THIS IS NOT THE PROPER SWITCH (WHICH WILL CAUSE FND_CHAIN
!	 TO KEEP SEARCHING), OR THE POINTER TO THE SWITCH BLOCK IF
!	 THE NAME MATCHES.
!
! SIDE EFFECTS
!
!	NONE
!
!--

    BEGIN

    MAP
	FILSW_PTR : REF FILSW_BLOCK;

    IF (CH$EQL (LEN_FSW_NAME, CH$PTR (FILSW_PTR [FSW_NAME]), LEN_FSW_NAME, CH$PTR (.SWITCH_NAME), 0))
    THEN
	.FILSW_PTR
    ELSE
	0

    END;					!OF SEL_SWITCH
END

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