Trailing-Edge
-
PDP-10 Archives
-
bb-r775d-bm_tops20_ks_upd_4
-
sources/prrange.bli
There are 10 other files named prrange.bli in the archive. Click here to see a list.
%TITLE 'PRRANGE - Parse a range'
MODULE PRRANGE (
IDENT = '3-003' ! File: PRRANGE.B36 Edit:CJG3003
) =
BEGIN
!
! COPYRIGHT (c) 1983, 1985 BY
! DIGITAL EQUIPMENT CORPORATION, MAYNARD, MASS.
! ALL RIGHTS RESERVED.
!
! 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: EDT -- The DEC Standard Editor
!
! ABSTRACT:
!
! Parse a range
!
! ENVIRONMENT: Runs on TOPS-20 only
!
! AUTHOR: Chris Gill, CREATION DATE: March 15, 1983
!
! MODIFIED BY:
!
! 3-001 - Creation. CJG 15-Mar-1983
! 3-002 - Fix "TYPE -1" so that it defaults to "TYPE .-1". CJG 9-Dec-1983
! 3-003 - Check for control-C being typed. CJG 5-Jan-1984
!--
%SBTTL 'DECLARATIONS'
!
! TABLE OF CONTENTS
!
REQUIRE 'EDTSRC:TRAROUNAM';
FORWARD ROUTINE
PA_ENDRAN : NOVALUE, ! Complete a compound range
EDT$$PA_RANGE; ! Parse a range specifier
!
! INCLUDE FILES:
!
REQUIRE 'EDTSRC:EDTREQ';
REQUIRE 'EDTSRC:PARLITS';
REQUIRE 'SYS:JSYS';
!
! EXTERNAL REFERENCES:
!
! In the routines
!
! MACROS:
!
MACRO
BITS (VAL) [] =
+(1 ^ (VAL - 1))
BITS (%REMAINING) %;
!
! OWN DATA
!
! This table dictates which atoms are allowed to follow which other atoms.
! The table is indexed by the number of the atom just processed and
! consists of bits indicating which atom is legal next.
!
OWN
RAN_NEXT_TBL : VECTOR [NUM_RAN+1] INITIAL (
BITS (RAN_NUMBER, RAN_DOT, RAN_STR, RAN_BEGIN, RAN_END, RAN_ORIG,
RAN_PLUS, RAN_MINUS, RAN_LAST, RAN_BUFFER, RAN_REST,
RAN_BEFORE, RAN_SELECT, RAN_WHOLE, RAN_ALL), ! Start
BITS (RAN_DOT, RAN_PLUS, RAN_MINUS), ! Number
BITS (RAN_PLUS, RAN_MINUS), ! "."
BITS (RAN_PLUS, RAN_MINUS), ! String
BITS (RAN_PLUS, RAN_MINUS), ! BEGIN
BITS (RAN_PLUS, RAN_MINUS), ! END
BITS (RAN_PLUS, RAN_MINUS, RAN_NUMBER), ! ORIGINAL
0,
0, ! LAST
BITS (RAN_ALL), ! BEFORE
BITS (RAN_ALL), ! REST
BITS (RAN_ALL), ! WHOLE
0, ! SELECT
BITS (RAN_NUMBER, RAN_STR, RAN_BEGIN, RAN_END,
RAN_LAST, RAN_BEFORE, RAN_REST,
RAN_WHOLE, RAN_PLUS, RAN_DOT,
RAN_MINUS, RAN_SELECT, RAN_ALL, RAN_ORIG), ! BUFFER
BITS (RAN_NUMBER), ! "+"
BITS (RAN_NUMBER, RAN_STR), ! "-"
BITS (RAN_NUMBER), ! FOR
BITS (RAN_NUMBER, RAN_DOT, RAN_STR, RAN_BEGIN, RAN_END,
RAN_PLUS, RAN_MINUS, RAN_ORIG), ! THRU
0,
BITS (RAN_STR), ! ALL
BITS (RAN_NUMBER, RAN_DOT, RAN_STR, RAN_BEGIN, RAN_END,
RAN_PLUS, RAN_MINUS, RAN_ORIG) ! AND
),
!+
! RAN_SLR_NEXT has flags which are used when a single line range has
! been completed.
!-
RAN_SLR_NEXT : VECTOR [4] INITIAL (
BITS (RAN_THRU, RAN_FOR, RAN_AND, RAN_ALL), ! Initial
BITS (RAN_ALL), ! THRU
BITS (RAN_ALL), ! FOR
BITS (RAN_AND, RAN_ALL) ! AND
);
%SBTTL 'EDT$$PA_RANGE - Parse a range node'
GLOBAL ROUTINE EDT$$PA_RANGE ( ! Parse a range
LOCATION ) = ! Where to put result pointer
BEGIN
!+
! FUNCTIONAL DESCRIPTION
!
! This subroutine is called to parse a range. Ranges may consist of
! two parts - a single line range, and a range type (such as AND, FOR, and
! THRU). A buffer name may, optionally, be present. Thus, the overall
! format of a range is,
!
! { LAST }
! { SELECT }
! {
! { BEFORE }
! [ BUFFER name ] { REST }
! { WHOLE } [ ALL string ]
! { { THRU SLR } }
! { SLR { AND SLR [AND ... ] } }
! { { FOR number } }
!
! Where, SLR refers to a single line range.
!
! Single line ranges can have the following format,
!
! { line-number }
! { . } { + number } { + ... }
! { BEGIN } { } { }
! { END } { - { number } } { - ... }
! { string } { { string } } { }
! { -blank- }
!
! The type of range being parsed is held in FLAGS2 and the type of atom
! just parsed is held in PRVCMD. These are used to index the tables
! RAN_NEXT_TBL, and RAN_SLR_NEXT which indicate which atom is allowed next.
! This routine operates in a loop until an error is detected or an atom does
! not parse.
!
! ROUTINE VALUE
!
! -1 - JSYS error or next atom is disallowed
! 0 - Reparse required
! +1 - All correct
!-
EXTERNAL
PA_BUFRNG : REF NODE_BLOCK,
PA_ANDLSTHD : REF NODE_BLOCK,
PA_CURCMD : REF NODE_BLOCK, ! Parse node
PA_THRURNG : REF NODE_BLOCK,
PA_CURRNG : REF NODE_BLOCK,
PA_NUMVAL,
PA_ERRNO, ! Error number
PA_CURTOK, ! Pointer to current atom
PA_CURTOKLEN, ! And its length
CSB : VECTOR [10],
FD_RC1,
FD_RC2,
FD_RC3,
FD_RCM,
FD_RS1,
FD_RS2,
FD_RS3,
FD_RS4,
FD_RS5,
FD_R81,
FD_R82,
FD_RNM,
FD_RNP,
FD_RNA,
FD_RSR,
FD_RNS,
FD_RNN,
FD_RNG,
FD_RNK,
FD_RN8,
FD_RN7,
FD_RN6,
FD_RN5,
FD_RN4,
FD_RN3,
FD_RN2,
FD_RN1,
FD_AND,
FD_ANC,
FD_VAL,
FD_QST,
MAX_LINES,
LNO0 : LNOVECTOR [14],
CC; ! Control-C flag
EXTERNAL ROUTINE
EDT$$CMP_LNO, ! Compare line numbers
EDT$$PA_SCANTOK, ! Get atom length
EDT$$PA_BUFFER, ! Get buffer name
EDT$$PA_LINE_NUM, ! Parse aline number
EDT$$PA_NUMBER, ! Get a number
EDT$$PA_NEW_NOD, ! Create a new node
EDT$$PA_CRERNGNOD; ! Create a new range node
LOCAL
C_FLAG, ! COMND flags
C_DATA, ! COMND data or pointer
C_FDB, ! FDB used in parse
CMDTYP, ! Type of current range atom
PRVCMD, ! Save previous node type
FLAGS2, ! Extra flags compound ranges
FD_PTR, ! Pointer to current FDB
MORE, ! Set TRUE if more to parse
THRU_SEEN, ! Set TRUE if THRU keyword seen
FOR_SEEN, ! Set TRUE if FOR keyword seen
AND_SEEN, ! Set TRUE if AND keyword seen
FLAG; ! Flags for next node allowed
MESSAGES ((QUOSTRREQ, NUMVALREQ, ERRRANSPC, NUMVALILL));
!+
! Preset the flags and (previous) command, and parse the first atom
!
CMDTYP = 0;
FLAG = .RAN_NEXT_TBL [0];
FLAGS2 = 0;
FD_PTR = FD_RNG;
THRU_SEEN = 0;
AND_SEEN = 0;
FOR_SEEN = 0;
MORE = 1;
!+
! Loop parsing range spec until error or end of specification
!-
WHILE .MORE DO
BEGIN
IF (NOT COMMAND (.FD_PTR)) THEN RETURN (-1);
IF (.CC NEQ 0) THEN RETURN (-1);
!+
! Exit loop if no parse
!-
IF ((.C_FLAG AND CM_NOP) NEQ 0) THEN EXITLOOP;
!+
! The atom parsed OK and it is time to do the appropriate thing with it.
!-
IF ((.C_FLAG AND CM_RPT) NEQ 0) THEN RETURN (0);
IF (.C_FDB<0,18> EQL FD_RNG) THEN
BEGIN
!+
! If a '%' was found the rescan for the keyword
!-
IF (NOT COMMAND (FD_RNK)) THEN RETURN (-1);
IF (.CC NEQ 0) THEN RETURN (-1);
IF ((.C_FLAG AND CM_NOP) NEQ 0) THEN RETURN (-1);
IF ((.C_FLAG AND CM_RPT) NEQ 0) THEN RETURN (0);
END;
PRVCMD = .CMDTYP;
CMDTYP = (SELECTONE .C_FDB<0,18> OF
SET
[ FD_RNK, FD_RNA, FD_RCM, FD_RN8, FD_RSR, FD_AND ] : .(.C_DATA)<0,18>;
[ FD_RNN, FD_VAL, FD_RS5 ] : RAN_NUMBER;
[ FD_RNS, FD_QST, FD_RS4 ] : RAN_STR;
[ FD_RN4, FD_RNP, FD_R81, FD_RS1 ] : RAN_PLUS;
[ FD_RN5, FD_RNM, FD_R82, FD_RS2 ] : RAN_MINUS;
[ FD_RN6, FD_RS3 ] : RAN_DOT;
[ FD_RN1, FD_RC3 ] : RAN_FOR;
[ FD_RN2, FD_RC1 ] : RAN_THRU;
[ FD_RN3, FD_RC2, FD_ANC ] : RAN_AND;
[ FD_RN7 ] : RAN_BUFFER;
TES);
!+
! If this atom was not allowed - return an error
!-
IF ((.FLAG AND 1 ^ (.CMDTYP - 1)) EQL 0) THEN
BEGIN
IF ((.RAN_SLR_NEXT [.FLAGS2 <0,18>] AND 1 ^ (.CMDTYP - 1)) EQL 0) THEN
BEGIN
PA_ERRNO = EDT$_ERRRANSPC;
RETURN (-1);
END;
PA_ENDRAN (.FLAGS2);
END;
FLAG = .RAN_NEXT_TBL [.CMDTYP];
!+
! Now do the right things for each of the possible cases
!-
CASE .CMDTYP FROM RAN_NUMBER TO NUM_RAN OF
SET
[ RAN_NUMBER ] :
BEGIN
!+
! Set up command table for legal items which can follow
!-
IF ((.THRU_SEEN) OR (.FOR_SEEN)) THEN FD_PTR = FD_RNA ELSE
IF (.AND_SEEN) THEN FD_PTR = FD_AND ELSE
FD_PTR = FD_RCM;
IF ((.PRVCMD EQL RAN_PLUS) OR (.PRVCMD EQL RAN_MINUS) OR
(.PRVCMD EQL RAN_FOR) OR (.PRVCMD EQL RAN_ORIG)) THEN
!+
! Treat a number following +, -, ORIGINAL, or FOR as a simple number.
!-
BEGIN
IF ((.C_DATA GEQ 2^17) OR (.C_DATA LSS 0)) THEN
BEGIN
PA_ERRNO = EDT$_NUMVALILL;
RETURN (-1);
END;
PA_CURRNG [RAN_VAL] = .C_DATA;
END
ELSE
!+
! If the previous atom was not one of these, then build a line number
!-
BEGIN
LOCAL STS;
IF ((PA_CURRNG = EDT$$PA_NEW_NOD (RANGE_NODE, .CMDTYP)) EQL 0)
THEN RETURN (-1);
STS = EDT$$PA_LINE_NUM (.C_DATA);
IF (.STS LEQ 0) THEN RETURN (.STS);
MOVELINE (PA_NUMVAL, PA_CURRNG [RAN_VAL]);
END;
END;
[ RAN_DOT ] :
BEGIN
!+
! Set up command table for legal items which can follow
!-
IF ((.THRU_SEEN) OR (.FOR_SEEN)) THEN FD_PTR = FD_RN8 ELSE
IF (.AND_SEEN) THEN FD_PTR = FD_AND ELSE
FD_PTR = FD_RNP;
IF ((PA_CURRNG = EDT$$PA_NEW_NOD (RANGE_NODE, .CMDTYP)) EQL 0)
THEN RETURN (-1);
END;
[ RAN_STR ] :
BEGIN
IF (.PRVCMD EQL RAN_ALL) THEN MORE = 0 ELSE
IF (.THRU_SEEN) THEN FD_PTR = FD_RN8 ELSE
IF (.AND_SEEN) THEN FD_PTR = FD_AND ELSE
FD_PTR = FD_RNP;
!+
! Create a new node when necessary and store the pointer and length
!-
IF ((.PRVCMD NEQ RAN_ALL) AND (.PRVCMD NEQ RAN_MINUS)) THEN
IF ((PA_CURRNG = EDT$$PA_NEW_NOD (RANGE_NODE, .CMDTYP)) EQL 0)
THEN RETURN (-1);
EDT$$PA_SCANTOK (1,0);
PA_CURRNG [RAN_VAL] = .PA_CURTOKLEN;
PA_CURRNG [STR_PNT] = .PA_CURTOK;
IF (.PRVCMD EQL RAN_MINUS) THEN PA_CURRNG [RAN_TYPE] = RAN_MINSTR;
END;
[ RAN_BEGIN, RAN_END, RAN_ORIG ] :
BEGIN
IF ((PA_CURRNG = EDT$$PA_NEW_NOD (RANGE_NODE, .CMDTYP)) EQL 0)
THEN RETURN (-1);
IF (.THRU_SEEN) THEN FD_PTR = FD_RN8 ELSE
IF (.AND_SEEN) THEN FD_PTR = FD_AND ELSE
FD_PTR = FD_RNP;
END;
[ RAN_BEFORE, RAN_REST, RAN_WHOLE] :
BEGIN
IF ((PA_CURRNG = EDT$$PA_NEW_NOD (RANGE_NODE, .CMDTYP)) EQL 0)
THEN RETURN (-1);
FD_PTR = FD_RNA;
END;
[ RAN_LAST, RAN_SELECT ] :
BEGIN
IF ((PA_CURRNG = EDT$$PA_NEW_NOD (RANGE_NODE, .CMDTYP)) EQL 0)
THEN RETURN (-1);
MORE = 0;
END;
[ RAN_BUFFER ] :
BEGIN
LOCAL STS;
!+
! Parse a buffer name and set a flag for later
!-
STS = EDT$$PA_BUFFER ();
IF (.STS LEQ 0) THEN RETURN (.STS);
FLAGS2 = .FLAGS2 OR F_BUFFER;
END;
[ RAN_FOR ] :
BEGIN
!+
! Create a new node and set some flags for later. Create a default if required.
!-
IF (.PRVCMD EQL 0) THEN
IF ((PA_CURRNG = EDT$$PA_NEW_NOD (RANGE_NODE, RAN_DOT)) EQL 0)
THEN RETURN (-1);
IF (EDT$$PA_CRERNGNOD (.CMDTYP) EQL 0) THEN RETURN (-1);
PA_ERRNO = EDT$_NUMVALREQ;
FLAGS2 <0,18> = F_FOR;
FOR_SEEN = 1;
FD_PTR = FD_VAL;
END;
[ RAN_PLUS, RAN_MINUS ] :
BEGIN
!+
! Create a default node if required.
!-
IF (.PRVCMD EQL 0) THEN
IF ((PA_CURRNG = EDT$$PA_NEW_NOD (RANGE_NODE, RAN_DOT)) EQL 0)
THEN RETURN (-1);
IF (EDT$$PA_CRERNGNOD (.CMDTYP) EQL 0) THEN RETURN (-1);
FD_PTR = FD_VAL;
END;
[ RAN_THRU ] :
BEGIN
!+
! Create a new node and set a flag for later. Create a default if required.
!-
IF (.PRVCMD EQL 0) THEN
IF ((PA_CURRNG = EDT$$PA_NEW_NOD (RANGE_NODE, RAN_DOT)) EQL 0)
THEN RETURN (-1);
IF ((PA_THRURNG = EDT$$PA_NEW_NOD (RANGE_NODE, 0)) EQL 0)
THEN RETURN (-1);
PA_THRURNG [RANGE1] = .PA_CURRNG;
FLAGS2 <0,18> = F_THRU;
FD_PTR = FD_RSR;
THRU_SEEN = 1;
END;
[ RAN_ALL ] :
BEGIN
LOCAL
SUB : REF NODE_BLOCK;
!+
! Complete any compound range outstanding and clear the flag.
! Then link the new range with the previous one
!-
PA_ENDRAN (.FLAGS2);
FLAGS2 <0,18> = 0;
IF (.PRVCMD EQL 0) THEN
IF ((PA_CURRNG = EDT$$PA_NEW_NOD (RANGE_NODE, RAN_WHOLE)) EQL 0)
THEN RETURN (-1);
SUB = .PA_CURRNG;
IF ((PA_CURRNG = EDT$$PA_NEW_NOD (RANGE_NODE, .CMDTYP)) EQL 0)
THEN RETURN (-1);
PA_CURRNG [NEXT_RANGE] = .SUB;
SUB [PREV_RANGE] = .PA_CURRNG;
PA_ERRNO = EDT$_QUOSTRREQ;
FD_PTR = FD_QST;
END;
[ RAN_AND ] :
!+
! Keep track of the current range for later linking
!-
BEGIN
IF (.PRVCMD EQL 0) THEN
BEGIN
PA_ERRNO = EDT$_ERRRANSPC;
RETURN (-1);
END;
PA_ANDLSTHD = .PA_CURRNG;
FLAGS2 <0,18> = F_AND;
AND_SEEN = 1;
FD_PTR = FD_RSR;
END;
[ INRANGE ] :
;
TES;
END;
!+
! Here when error parsing or logical end of specification reached
! Complete specification and return
!-
!+
! If a buffer name was supplied, link it in now unless the last atom
! should have had something following it.
!-
SELECTONE .CMDTYP OF
SET
[ 0 ] :
BEGIN
!+
! This is a null range - make sure it is stored as such.
!-
IF ((PA_CURRNG = EDT$$PA_NEW_NOD (RANGE_NODE, RAN_NULL)) EQL 0)
THEN RETURN (-1);
IF (.LOCATION EQL 1) THEN
PA_CURCMD [RANGE1] = .PA_CURRNG
ELSE
PA_CURCMD [RANGE2] = .PA_CURRNG;
RETURN (1);
END;
[ RAN_FOR ] :
RETURN (-1);
[ RAN_ALL ] :
RETURN (-1);
[ RAN_THRU ] :
IF ((PA_CURRNG = EDT$$PA_NEW_NOD (RANGE_NODE, RAN_DOT)) EQL 0)
THEN RETURN (-1);
[ RAN_BUFFER ] :
BEGIN
!+
! This is a null range - make sure it is marked as such
!-
IF ((PA_CURRNG = EDT$$PA_NEW_NOD (RANGE_NODE, RAN_NULL)) EQL 0)
THEN RETURN (-1);
IF (.LOCATION EQL 1) THEN
PA_CURCMD [RANGE1] = .PA_CURRNG
ELSE
PA_CURCMD [RANGE2] = .PA_CURRNG;
END;
[ OTHERWISE ] :
;
TES;
PA_ENDRAN (.FLAGS2);
IF ((.FLAGS2 AND F_BUFFER) NEQ 0) THEN
BEGIN
IF (.PA_BUFRNG NEQ .PA_CURRNG) THEN PA_BUFRNG [RANGE1] = .PA_CURRNG;
PA_CURRNG = .PA_BUFRNG;
END;
!+
! Finally, link the range to the command
!-
IF (.LOCATION EQL 1) THEN
PA_CURCMD [RANGE1] = .PA_CURRNG
ELSE
PA_CURCMD [RANGE2] = .PA_CURRNG;
RETURN (1);
END;
%SBTTL 'PA_ENDRAN - Complete a compound range'
ROUTINE PA_ENDRAN (
FLAG) : NOVALUE =
!+
! FUNCTIONAL DESCRIPTION
!
! This routine tidies up the compound range which was being evaluated last.
! If no such range was in the command, then the right half of FLAG will
! be zero. The tidy-up operation depends on the type of compound range
! being processed.
!
BEGIN
EXTERNAL
PA_THRURNG : REF NODE_BLOCK,
PA_ANDLSTHD : REF NODE_BLOCK,
PA_CURRNG : REF NODE_BLOCK;
BEGIN
!+
! Complete the previous compound range node before continuing
!-
CASE .FLAG<0,18> FROM F_SLR TO F_AND OF
SET
[ F_SLR ] :
; ! Nothing to do
[ F_THRU ] :
BEGIN
!+
! Link the THRU range node in
!-
PA_THRURNG [RAN_TYPE] = RAN_THRU;
IF (.PA_CURRNG NEQ .PA_THRURNG) THEN
PA_THRURNG [RANGE2] = .PA_CURRNG;
PA_CURRNG = .PA_THRURNG;
END;
[ F_FOR ] :
; ! Nothing to do
[ F_AND ] :
BEGIN
LOCAL ARANGE : REF NODE_BLOCK;
ARANGE = .PA_ANDLSTHD;
!+
! Find the last range so we can add the new one to the end
!-
WHILE (.ARANGE [NEXT_RANGE] NEQA 0) DO
ARANGE = .ARANGE [NEXT_RANGE];
ARANGE [NEXT_RANGE] = .PA_CURRNG;
PA_CURRNG [PREV_RANGE] = .ARANGE;
PA_CURRNG = .PA_ANDLSTHD;
END;
TES;
RETURN (1);
END;
END;
END
ELUDOM