Google
 

Trailing-Edge - PDP-10 Archives - decuslib10-07 - 43,50455/strmac.doc
There are 2 other files named strmac.doc in the archive. Click here to see a list.
								REPEAT 0,<
UNV:STRMAC.UNV DEFINES THE FOLLOWING ACCUMULATOR ASSIGNMENTS.

R0=0		FOR VERY TEMPORARY USE
T1-T4=1-4	FOR TEMPORARY USE, NOT USUALLY PRESERVED IN SUBROUTINES
P1-P4=5-10	NORMALLY PRESERVED IF USED IN A SUBROUTINE
R1-R4=11-14	USUALLY DEDICATED WITH GLOBAL SIGNIFICANCE THROUGHOUT PROGRAM
LP=15		LOCAL PUSHDOWN STORAGE POINTER, USED BY LOCAL MACRO
PC=16		PARAMETER LIST POINTER, USED BY CALL MACRO AND FORTRAN
P=17		PUSHDOWN POINTER, USED BY CALL MACRO AND FORTRAN

UNV:STRMAC.UNV DEFINES THE FOLLOWING MACROS FOR GENERAL USE.

STRIN.	HGHSEG
		SHOULD ALWAYS BE USED WHEN STRMAC IS USED.
		INITIALIZES VARIOUS SYMBOLS USED BY OTHER MACROS AND REQUESTS
		LINK TO LOAD REL:STRSUB WHICH CONTAINS THE FOLLOWING ROUTINES:
			SKP.RT	DOES A SKIP RETURN FOR THE SRETURN MACRO
			RST.PC	RESTORES PC FOR THE SUBR MACRO
			RST.LP	RESTORES LP FOR THE LOCAL MACRO
			CAL.FS	CALLS FORTRAN SUBROUTINES FOR THE CALL$F MACRO
			S.RXRY	SAVES AC'S RX THROUGH RY, THE FOLLOWING
				ROUTINES ARE IN STRSUB: S.R0R0,
					S.T1T1, S.T1T2, S.T1T3, S.T1T4,
					S.P1P1, S.P1P2, S.P1P3, S.P1P4,
					S.P1R1, S.P1R2, S.P1R3, S.P1R4,
					S.R1R1, S.R1R2, S.R1R3, AND S.R1R4.
		IF THE ARGUMENT IS GIVEN AS "HGHSEG", STRSUB IS LOADED INTO
		THE HIGH SEGMENT.  IF THE ARGUMENT IS NOT GIVEN, STRSUB IS
		LOADED INTO THE LOW SEGMENT.

DFN	SYM,VAL
		DEFINES SYM=VAL

BLK	SYM,SIZ,<SYMLST>
		ALLOCATES A BLOCK OF SIZ WORDS LABELED SYM.
		IF SIZ IS NOT PRESENT BLOCK SIZE IS 1.
		THE BLOCK IS ALLOCATED IN THE LOW SEG WHETHER OR NOT
		THE CURRENT LOCATION COUNTER IS IN THE HIGH OR LOW SEG.
		IF SYMLST IS PRESENT, THE 1ST SYMBOL IN THE LIST IS EQUATED TO
		THE LOCATION OF THE 2ND WORD OF THE BLOCK,  THE 2ND SYMBOL TO
		THE 3RD LOCATION, THE 3RD TO THE 4TH, ETC.

PROG	PRGNAM,PDLSIZ,RUNOFF,RUNFLS
		DEFINES SYMBOL PRGNAM FOR START OF PROGRAM AND ENDPRG MACRO.
		GENERATES TDZA T1,T1 AND MOVEI T1,1 FOR RUN OFFSET.
		IF RUNOFF IS PRESENT, ALLOCATES A BLOCK OF 1 WORD LABELED
		RUNOFF AND GENERATES A MOVEM T1,RUNOFF TO STORE THE OFFSET.
		IF RUNFLS IS PRESENT, ALLOCATES A BLOCK OF 4 WORDS LABELED
		RUNFLS AND GENERATES MOVEMS TO STORE AC'S 11,0,17,7 IN THE
		BLOCK TO SAVE THE DEV,FIL,EXT, AND PPN FROM THE RUN UUO.
		IF PDLSIZ IS PRESENT, ALLOCATES A BLOCK OF PDLSIZ WORDS LABELED
		PDL AND GENERATES A MOVE P,[IOWD PDLSIZ,PDL].

ENDPRG		GENERATES A MACRO END STATEMENT TO END THE PROGRAM AND
		SET THE PROGRAM BEGIN ADDRESS TO THE LABEL IN THE PROG MACRO.
CALL	SUBNAM,<ARGLST>
		GENERATES A PUSHJ TO SUBNAM.
		IF ARGLST IS PRESENT, AN ARGUMENT LIST IS GENERATED AND
		A HRRI IS GENERATED TO LOAD PC WITH THE ADDRESS OF THE
		ARGUMENT LIST.  HRRI IS USED BECAUSE OF THE SYSTEM WHICH
		AUTOMATICALLY RESTORES PC TO WHAT IT WAS BEFORE THE CALL.
		IF THERE IS NO ARGLST, PC IS NOT ALTERED.
		THE ARG LIST GENERATED IS ACCEPTABLE TO FORTRAN BUT DOES
		NOT FOLLOW THE FORTRAN STANDARD.  THERE ARE NO ARG TYPES AND
		THE ARG COUNT WORD IS NOT PRESENT PRECEEDING THE ARG LIST.
		IF FORTRAN EVER DEMANDS THESE FEATURES, THE MACRO CAN EASILY
		BE CHANGED TO CREATE THEM WITHOUT ANY OTHER PROGRAM CHANGES.

CALL$R	SUBNAM,<ARGLST>
		THIS IS EXACTLY LIKE CALL EXCEPT THAT A JRST IS GENERATED
		INSTEAD OF A PUSHJ. CALL$R IS LIKE A CALL FOLLOWED BY A RETURN.

CALL$F	SUBNAM,<ARGLST>
		THIS IS SIMILAR TO CALL BUT IS USED FOR CALLING FORTRAN
		SUBROUTINES WHEN IT IS IMPORTANT THAT THE AC'S ARE NOT
		DESTROYED.  CALL$F CALLS CAL.FS IN STRSUB WHICH CALLS SUBNAM.
		CALL.FS SAVES AND RESTORES AC'S P1-P4, R1-R4, LP, AND PC.

SUBR	SUBNAM,<ARGLST>
		DEFINES SYMBOL SUBNAM FOR START OF SUBROUTINE.
		IF ARGLST IS PRESENT A MACRO IS DEFINED FOR EACH ARG IN ARGLST.
		THE NAME OF THE ARG MACRO IS THE ARG AND THE DEFINITION IS
		@X(PC) WHERE X IS 0,1,2,ETC FOR THE 1ST,2ND,3RD,3TC ARG.  IN
		THE SUBROUTINE, THE ARG NAME CAN BE USED TO REFERENCE THE ARG.
		IF ARGLST IS PRESENT, THE PC IS SAVED ON ENTRY AND THE PC THAT
		THE CALLING PROGRAM HAD BEFORE THE CALL IS AUTOMATICALLY
		RESTORED ON RETURN BY RST.PC IN STRSUB.

RETURN		GENERATES POPJ P,

SRETURN		DOES A SKIP RETURN BY JRSTING TO SKP.RT IN STRSUB.

ENDSUB		GENERATES NO CODE BUT MAY BE USED AT THE END OF A SUBROUTINE
		TO CHECK THE STACK LEVEL TO FIND STRUCTURING ERRORS.

LOCAL	<<VAR1,INI1>,<VAR2,INI2>,...>
		GENERATES CODE TO ALLOCATE STORAGE ON THE PDL FOR A LIST
		OF LOCAL VARIABLES.  FOR EACH LOCAL VARIABLE, A MACRO IS
		DEFINED BY THE SAME NAME OF THE FORM X(LP) WHICH ALLOWS
		THE VARIABLE TO BE REFERENCED IN LOCAL STORAGE.
		IF INI? IS PRESENT, VAR? IS INITIALIZED TO INI?.
		CODE IS ALSO GENERATED TO CAUSE THE STORAGE TO BE
		AUTOMATICALLY FREED ON RETURN FROM THE SUBROUTINE.
		NOTE: LOCAL VARIABLES MAY BE PASSED TO SUBROUTINES AS
		PARAMETERS BUT THE CALLING SUBROUTINE MAY ONLY USE THE
		CORRESPONDING PARAMETER UP UNTIL THE POINT WHERE IT SETS UP
		ITS LOCAL STORAGE.  THE PARAMETER WHICH CORESPONDS TO A LOCAL
		VARIABLE IN THE CALLING SUBROUTINE MAY HOWEVER BE USED TO
		INITIALIZE A LOCAL VARIABLE IN THE CALLED SUBROUTINE.
UNV:STRMAC.UNV DEFINES THE FOLLOWING MACROS USEFUL FOR STRUCTURED PROGRAMMING.

IFSKIP		MAY BE USED TO BEGIN AN IF-TYPE CONDITIONAL STRUCTURE.  IFSKIP
		GENERATES A JRST TO THE ASSOCIATED ELSE PART OR IF THERE IS
		NO ASSOCIATED ELSE GENERATES A JRST TO THE ASSOCIATED ENDIF.
		IFSKIP USUALLY FOLLOWS AN INSTRUCTION WHICH CONDITIONALLY
		SKIPS.

IFNOSKIP	MAY BE USED TO BEGIN AN IF-TYPE CONDITIONAL STRUCTURE.
		IFNOSKIP IS SIMILAR TO IFSKIP EXCEPT A CAIA IS GENERATED FIRST
		SO THAT THE TRUE PART IS ENTERED IF THERE IS NO SKIP FROM THE
		INSTRUCTION BEFORE THE IFNOSKIP.

IFNOT	<TSTINS>
		MAY BE USED TO BEGIN AN IF-TYPE CONDITIONAL STRUCTURE.  TSTINS
		IS A CONDITIONAL JUMP INSTRUCTION.  IFNOT GENERATES THE
		JUMP ADDRESS FOR TSTINS TO THE ASSOCIATED ELSE PART OR IF
		THERE IS NO ASSOCIATED ELSE TO THE ASSOCIATED ENDIF.
		IF THE CONDITION OF TSTINS IS NOT TRUE THE TRUE PART IS
		ENTERED, OTHERWISE TSTINS JUMPS TO THE ELSE PART OR THE ENDIF.

ELSE		MAY BE USED IN AN IF-TYPE CONDITIONAL STRUCTURE TO END
		THE TRUE PART AND BEGIN THE FALSE PART.  ELSE GENERATES
		A JRST TO THE ASSOCIATED ENDIF MACRO AND A LABEL FOR
		THE ASSOCIATED IF MACRO TO JRST TO.
ENDIF		MUST BE USED TO END AN IF-TYPE CONDITIONAL STRUCTURE.  ENDIF
		GENERATES A LABEL WHICH IS THE TARGET OF A JRST IN AN
		ASSOCIATED IF OR ELSE.

SELECT	AC,OF,N
		MUST BE USED TO BEGIN A CASE-TYPE CONDITIONAL STRUCTURE.
		A CASE-TYPE CONDITIONAL STRUCTURE IS A STRUCTURE WHICH
		CONTAINS SEVERAL CASES.  EACH CASE IS PRECEEDED BY
		EITHER THE CASE MACRO, THE CASEIF MACRO, THE CASENOT MACRO
		OR THE ELSECASE MACRO.  AT MOST ONE OF THE CASES IS SELECTED
		THEN A JRST IS MADE TO THE END OF THE CASE-TYPE CONDITIONAL
		STRUCTURE.
		THERE ARE 2 TYPES OF CASE-TYPE CONDITIONAL STRUCTURES.
		IN A DISPATCH TYPE SELECT, THE CASE SELECTOR IS A POSITIVE
		INTEGER IN THE SPECIFIED AC RANGING FROM 1 TO N.  CODE IS
		GENERATED TO CHECK THAT THE CONTENTS OF THE AC IS IN RANGE
		OTHERWISE THE CODE JRSTS TO THE ELSECASE IF IT IS PRESENT OR
		TO THE ENDSEL ENDING THE STRUCTURE.  THE DISPATCH IS MADE
		BY JUMPING THROUGH A VECTOR OF ADDRESSES OF THE VARIOUS
		CASES.  EACH CASE IS HEADED BY A CASE MACRO WHOSE ARGUMENT
		IS A LIST OF ONE OR MORE INTEGERS IN THE RANGE 1 TO N.  THAT
		CASE IS ENTERED WHEN AC HAS ONE OF THE VALUES IN THE LIST.
		IF ONE OF THE VALUES IN THE RANGE 1 TO N DOES NOT HAVE AN
		ASSOCIATED CASE, THEN THE ELSECASE IS SELECTED OR IF THERE
		IS NO ELSECASE, THE CASE-TYPE CONDITIONAL STRUCTURE IS
		EXITED BY JRSTING TO THE ENDSEL.
		IN A CHECKING CHAIN TYPE SELECT, THE SPECIFIED AC MAY CONTAIN
		ANY VALUE.  IN THIS CASE THE SELECT MACRO GENERATES NO CODE.
		INSTEAD, CODE IS GENERATED AT THE BEGINNING OF EACH CASE TO
		CHECK WHETHER OR NOT TO EXECUTE THAT CASE.
CASE	<VALUE-LIST>
		MUST BE USED TO HEAD A CASE FOR A DISPATCH TYPE SELECT.
		MAY BE USED TO HEAD A CASE FOR A CHECKING CHAIN TYPE SELECT.
		A JRST IS GENERATED FIRST SO THAT THE PRECEEDING CASE WILL
		EXIT TO THE ENDSEL ENDING THE STRUCTURE.
		FOR DISPATCH SELECT, EACH VALUE IN THE VALUE LIST MUST BE IN
		THE RANGE 1 TO N WHERE N IS FROM THE SELECT MACRO.
		A LABEL IS GENERATED FOR EACH VALUE IN THE LIST WHICH IS
		JUMPED TO FROM A JUMP VECTOR IN THE SELECT.
		FOR A CHECKING TYPE SELECT, THE LIST MAY CONTAIN ANY VALUES.
		A LABEL IS GENERATED SO THAT THE PRECEEDING CASE CAN JUMP
		TO THIS CASE IF THE CHECKING CODE ON IT FAILS.  THEN CAI OR
		CAM INSTRUCTIONS ARE GENERATED TO COMPARE THE AC SPECIFIED IN
		THE SELECT MACRO WITH THE VALUES IN THE LIST.  IF NONE OF
		THE VALUES MATCH, A JRST IS GENERATED TO THE NEXT CASE, OR
		THE ELSECASE, OR THE ENDSEL DEPENDING ON WHICH IS NEXT.
		IF THIS TYPE OF CASE IS NOT USED IN A CHECKING CHAIN TYPE OF
		SELECT, THEN THE AC DOES NOT NEED TO BE GIVEN ON THE SELECT.

CASEIF	<SKPINS>
		MAY BE USED TO HEAD A CASE FOR A CHECKING CHAIN TYPE SELECT.
		A JRST IS GENEARATED FIRST SO THAT THE PRECEEDING CASE WILL
		EXIT TO THE ENDSEL ENDING THE STRUCTURE.
		A LABEL IS THEN GENERATED SO THAT THE PRECEEDING CASE CAN
		JUMP TO THIS CASE IF THE CHECKING CODE ON IT FAILS.  THEN
		SKPINS IS GENERATED WHICH SHOULD BE A CONDITIONAL SKIP TYPE
		INSTRUCTION WHICH WILL SKIP IF THIS CASE SHOULD BE ENTERED.
		THEN A JRST IS GENERATED WHICH WILL JUMP TO THE NEXT CASE,
		ELSECASE OR ENDSEL IF SKPINS DOES NOT SKIP.

CASENOT	<TSTINS>
		MAY BE USED TO HEAD A CASE FOR A CHECKING CHAIN TYPE SELECT.
		THIS MACRO IS SIMILAR TO CASEIF EXCEPT THAT INSTEAD OF A
		CONDITIONAL SKIP INSTRUCTION THE ARG IS A CONDITIONAL JUMP
		INSTRUCTION.  THE MACRO GENERATES THE JUMP ADDRESS SUCH THAT
		IF THE CONDITION IS TRUE IT JUMPS TO CHECK THE NEXT CASE,
		OTHERWISE THIS CASE IS ENTERED.

ELSECASE	MAY BE USED TO HEAD THE LAST CASE OF EITHER TYPE OF SELECT.
		ELSECASE IS OPTIONAL BUT IF PRESENT IT IS ENTERED IF FOR
		A DISPATCH TYPE SELECT THE VALUE IN THE AC IS LESS THAN 1 OR
		GREATER THAN N OR IF THERE IS NO CASE FOR THAT VALUE OR
		FOR A CHECKING TYPE SELECT IF NONE OF THE PRECEEDING CASES
		IN THE CHECKING CHAIN HAVE BEEN ENTERED YET.
		A JRST IS GENEARATED FIRST SO THAT THE PRECEEDING CASE WILL
		EXIT TO THE ENDSEL ENDING THE STRUCTURE.  THEN A LABEL
		IS GENERATED FOR EACH MISSING CASE IN A DISPATCH TYPE SELECT.

ENDSEL		MUST BE USED TO END A CASE-TYPE CONDITIONAL STRUCTURE.
		GENERATES A LABEL WHICH EACH CASE EXITS TO AND A LABEL
		FOR EACH MISSING CASE IN A DISPATCH TYPE SELECT IF THERE IS
		NO ELSECASE.
LOOP		MUST BE USED TO BEGIN A LOOP STRUCTURE.  GENERATES A LABEL
		FOR THE TOP OF THE LOOP.

WHILESKIP	MAY BE USED IN A LOOP STRUCTURE TO EXIT FROM LOOP.
		WHILESKIP IS USUALLY USED FOLLOWING A CONDITIONAL SKIP
		INSTRUCTION TO CONDITIONALLY EXIT FROM A LOOP WHEN THE
		INSTRUCTION DOES NOT SKIP.

WHILE	<TSTINS>
		MAY BE USED IN A LOOP STRUCTURE TO CONDITIONALLY EXIT FROM
		THE LOOP.  TSTINS IS A CONDITIONAL JUMP INSTRUCTION WHOSE
		ADDRESS IS GENERATED BY THE MACRO TO JUMP AROUND A JUMP OUT
		OF THE LOOP.  THEREFORE THE LOOP IS EXITED WHEN THE CONDITION
		IS NOT MET.

UNTILSKIP	MAY BE USED IN A LOOP STRUCTURE TO EXIT FROM LOOP.
		UNTILSKIP IS LIKE WHILESKIP EXCEPT THAT UNTILSKIP GENERATES
		A CAIA FIRST SO THAT THE LOOP IS EXITED WHEN THE PRECEEDING
		SKIP INSTRUCTION SKIPS.

UNTIL	<TSTINS>
		MAY BE USED IN A LOOP STRUCTURE TO CONDITIONALLY EXIT FROM
		THE LOOP.  TSTINS IS A CONDITIONAL JUMP INSTRUCTION WHOSE
		ADDRESS IS GENERATED BY THE MACRO TO JUMP OUT OF THE LOOP
		WHEN THE CONDITION IS MET.

EXITLOOP	MAY BE USED IN A LOOP STRUCTURE TO UNCONDITIONALLY EXIT
		FROM THE LOOP.

NEXTLOOP	MAY BE USED IN A LOOP STRUCTURE TO UNCONDITIONALLY JUMP TO
		THE TOP OF THE LOOP.

ENDLOOP	<TSTINS>
		MUST BE USED TO END A LOOP STRUCTURE.
		TSTINS IS OPTIONAL.  IF IT IS NOT PRESENT A JRST IS GENERATED
		TO THE TOP OF THE LOOP.  IF TSTINS IS PRESENT, IT SHOULD
		BE A CONDITIONAL JUMP INSTRUCTION WHICH IS GENERATED INSTEAD
		THE JRST TO THE TOP OF THE LOOP TO PROVIDE FOR CONDITIONAL
		EXIT FROM THE LOOP.
		A LABEL IS GENERATED AT THE END OF THE LOOP FOR ANY OF THE
		ABOVE LOOP EXIT MACROS TO JUMP TO.
UNV:STRMAC.UNV USES THE FOLLOWING INTERNAL DEFINITIONS.

VARIABLES USED INTERNALLY BY STRMAC, NOT FOR GENERAL USE.

.LBL		NEXT AVAILABLE LABEL NUMBER
.E		ENDSEL LABEL
.N		NUMBER OF CASES IN A DISPATCH TYPE SELECT
.R		AC TO USE IN A CHECKING CHAIN TYPE SELECT
.F		FLAGS FIRST CASE OF A CHECKING CHAIN TYPE SELECT
.L		LOOP LABEL
..		NEXT AVAILALBE LOCATION IN LOW SEG FOR BLK MACRO

MACROS USED INTERNALLY BY STRMAC, NOT FOR GENERAL USE.

$LDPC		INSTRUCTION TO LOAD PC FOR SUBROUTINE CALLS
$DEFARG		DEFINE SUBROUTINE ARGUMENTS
$VARDEF		DEFINE LOCAL VARIABLES
$VARDF2		DEFINE LOCAL VARIABLES
$PUSH		PUSH
$POP		POP
$DL		DEFINE A LABEL
$LR		REFERENCE A LABEL
$CMP		GENERATE A CAI OR CAM INSTRUCTION
$EC		GENERATE MISSING CASE LABELS FOR DISPATCH TYPE SELECT

******************************************************************************
* EXAMPLES * EXAMPLES * EXAMPLES * EXAMPLES * EXAMPLES * EXAMPLES * EXAMPLES *
******************************************************************************
EXAMPLE OF USING STRMAC AND THE STRIN., DFN, PROG, AND ENDPRG MACROS
****************************************************************
TITLE	TSTPRG
SEARCH	STRMAC			; GETS STRMAC DEFINITIONS
STRIN.				; INITIALIZES STRMAC
SALL

DFN	PDLSIZ,40		; DEFINES PDLSIZ=40

PROG	TSTPRG,PDLSIZ		; GENERATES LABEL TSTPRG AND ALLOCATES A BLOCK
				; OF 40 WORDS AND SETS UP AC P POINTING TO THE
				; THE BLOCK FOR A PUSHDOWN LIST
.
.
.
ENDPRG				; GENERATES MACRO END STATEMENT
				; WITH TSTPRG AS START ADDRESS
******************************************************************************
>;END REPEAT 0
UNIVER	STRMAC
PASS2
.DIRECT	.NOBIN

DEFINE	DFN(SYM,VAL)<SYM=VAL>	; DEFINE A SYMBOL

DFN	R0,0
DFN	T1,R0+1		; TEMPORARY AC'S
DFN	T2,T1+1
DFN	T3,T2+1
DFN	T4,T3+1
DFN	P1,T4+1		; PRESERVED AC'S
DFN	P2,P1+1
DFN	P3,P2+1
DFN	P4,P3+1
DFN	R1,P4+1		; RESERVED AC'S
DFN	R2,R1+1
DFN	R3,R2+1
DFN	R4,R3+1
DFN	LP,R4+1		; LOCAL STORAGE POINTER
DFN	PC,16		; PARAMETER LIST ADDRESS FOR SUBR CALLS
DFN	P,17		; PDL POINTER
DEFINE	STRIN.(STRSEG)<
IFIDN	<STRSEG><HGHSEG>,<
  .TEXT	"/SEARCH/SEGMENT:HIGH REL:STRSUB"
>;END IFIDN
IFDIF	<STRSEG><HGHSEG>,<
  .TEXT	"/SEARCH/SEGMENT:LOW REL:STRSUB"
>;END IFDIF
.DIRECT	.XTABM
.LBL=1
.E=0
.N=0
.R=0
.F=0
.L=0
..=0
>;END DEFINE

DEFINE	BLK(SYM,SIZ,SYMLST)<
.S=.
IFGE	.S-400000,<
		RELOC	..
>;END IFG
SYM=.
.K=1
IRP	SYMLST,<
  SYMLST=.+.K
  .K=.K+1
>;END IRP
IFNB	<SIZ>,<
		BLOCK SIZ
>;END IFNB
IFB	<SIZ>,<
		BLOCK 1
>;END IFB
..=.
IFGE	.S-400000,<
		RELOC	.S
>;END IFG
>;END DEFINE
DEFINE	PROG(PRGNAM,PDLSIZ,RUNOFF,RUNFLS)<
IFNB	<RUNOFF>,<
  BLK RUNOFF
>;END IFNB
IFNB	<RUNFLS>,<
  BLK	RUNFLS,4
>;END IFNB
IFNB	<PDLSIZ>,<
  BLK	PDL,PDLSIZ
>;END IFNB
OPDEF	$LDPC	[MOVEI PC,]
.P=.
PRGNAM:		TDZA T1,T1
		MOVEI T1,1
IFNB	<RUNOFF>,<
		MOVEM T1,RUNOFF
>;END IFNB
IFNB	<RUNFLS>,<
		MOVEM 11,RUNFLS
		MOVEM  0,RUNFLS+1
		MOVEM 17,RUNFLS+2
		MOVEM  7,RUNFLS+3
>;END IFNB
IFNB	<PDLSIZ>,<
		MOVE P,[IOWD PDLSIZ,PDL]
>;END IFNB
>;END DEFINE

DEFINE	ENDPRG<
		END .P
>;END DEFINE
DEFINE	CALL(SUBNAM,ARGLST)<
IFNB	<ARGLST>,<
		$LDPC [
  IRP ARGLST,<
		ARGLST
  >;END IRP
		]
>;END IFNB
		PUSHJ P,SUBNAM
>;END DEFINE

DEFINE	CALL$R(SUBNAM,ARGLST)<
IFNB	<ARGLST>,<
		HRRI PC,[
  IRP ARGLST,<
		ARGLST
  >;END IRP
		]
>;END IFNB
		JRST SUBNAM
>;END DEFINE
DEFINE	CALL$F(SUBNAM,ARGLST)<
		EXTERN SUBNAM
		PUSHJ P,CAL.FS##
		[
		SUBNAM
IFNB	<ARGLST>,<
  IRP ARGLST,<
		ARGLST
  >;END IRP
>;END IFNB
		]+1
>;END DEFINE

DEFINE	SUBR(SUBNAM,ARGLST)<
OPDEF	$LDPC	[HRRI PC,]
SUBNAM:		ENTRY SUBNAM
IFNB	<ARGLST>,<
  .K=0
  IRP	ARGLST,<
    $DEFARG(ARGLST,\.K)
    .K=.K+1
  >;END IRP
		PUSH P,PC
		HRL PC,P
		PUSH P,RST.PC##
>;END IFNB
>;END DEFINE

DEFINE	$DEFARG(ARG,DSP)<
DEFINE ARG<@DSP(PC)>
>;END DEFINE

OPDEF	RETURN	[POPJ P,]
OPDEF	SRETURN	[JRST SKP.RT##]

DEFINE	ENDSUB<
IF2	,<
  IFN	.E+.L,<
    PRINTX ERROR IN PROGRAM STRUCTURE
  >;END IFN
>;END IF2
>;END DEFINE
DEFINE	LOCAL(VARLST)<
		PUSH P,P
.K=0
IRP	VARLST,<
  .K=.K+1
  $VARDEF(\<.K+1>,VARLST)
>;END IRP
		EXCH LP,-.K(P)
		PUSH P,RST.LP##
>;END DEFINE

DEFINE	$VARDEF(DSP,VARVAL)<
$VARDF2(DSP,VARVAL)
>;END DEFINE

DEFINE	$VARDF2(DSP,VAR,VAL)<
DEFINE	VAR<DSP(LP)>
		PUSH P,VAL
>;END DEFINE
DEFINE	$DL(LBLNUM)<$L'LBLNUM:>

DEFINE	$LR(LBLNUM)<$L'LBLNUM>

DEFINE	$DC(LBLNUM)<IFNDEF	$L'LBLNUM,<$L'LBLNUM:>>

DEFINE	IFSKIP<
$PUSH	.E
.E=.LBL
.LBL=.LBL+1
		JRST $LR(\.E)
>;END DEFINE

DEFINE	IFNOSKIP<
$PUSH	.E
.E=.LBL
.LBL=.LBL+1
		CAIA
		JRST $LR(\.E)
>;END DEFINE

DEFINE	IFNOT(TSTINS)<
$PUSH	.E
.E=.LBL
.LBL=.LBL+1
		TSTINS $LR(\.E)
>;END DEFINE

DEFINE	ELSE<
		JRST $LR(\.LBL)
$DL(\.E)
.E=.LBL
.LBL=.LBL+1
>;END DEFINE

DEFINE	ENDIF<
$DL(\.E)
$POP	.E
>;END DEFINE
DEFINE	SELECT(AC,OF,N)<
$PUSH	.E,.N,.R
IFNB	<N>,<
  .E=.LBL+1
  .N=N
  .R=-1
  .LBL=.LBL+N+2
		JUMPLE AC,$LR(\<.E-1>)
		CAILE AC,N
		JRST $LR(\<.E-1>)
		JRST @.(AC)
  REPEAT	N,<
    .E=.E+1
		$LR(\.E)
  >;END REPEAT
  .E=.E-N
>;END IFNB
IFB	<N>,<
  .E=.LBL
  .N=.LBL+1
  .R=AC
  .LBL=.LBL+2
  .F=1
>;END IFB
>;END DEFINE
DEFINE	CASE(C)<
IFL	.R,<
		JRST $LR(\.E)
  IRP	C,<
    $DL(\<.E+C>)
  >;END IRP
>;END IFL
IFGE	.R,<
  IFE	.F,<
		JRST $LR(\.E)
    $DL(\.N)
    .N=.LBL
    .LBL=.LBL+1
  >;END IFE
  .F=0
  .K=-1
  IRP	C,<
    .K=.K+1
  >;END IRP
  IFE	.K,<
    $CMP(E,.R,C)
		JRST $LR(\.N)
  >;END IFE
  IFG	.K,<
    IRP	C,<
      $CMP(N,.R,C)
		JRST $LR(\.LBL)
    >;END IRP
		JRST $LR(\.N)
    $DL(\.LBL)
    .LBL=.LBL+1
  >;END IFG
>;END IFGE
>;END DEFINE

DEFINE	$CMP(C,AC,V)<
IFE	<-1B17&V>,<
		CAI'C AC,V
>;END IFE
IFN	<-1B17&V>,<
		CAM'C AC,[V]
>;END IFN
>;END DEFINE
DEFINE	CASEIF(SKPCHK)<
IFE	.F,<
		JRST $LR(\.E)
  $DL(\.N)
  .N=.LBL
  .LBL=.LBL+1
>;END IFE
.F=0
		SKPCHK
		JRST $LR(\.N)
>;END DEFINE

DEFINE	CASENOT(TSTINS)<
IFE	.F,<
		JRST $LR(\.E)
  $DL(\.N)
  .N=.LBL
  .LBL=.LBL+1
>;END IFE
.F=0
		TSTINS $LR(\.N)
>;END DEFINE

DEFINE	$EC<
$DC(\<.E-1>)
REPEAT	.N,<
  .E=.E+1
  $DC(\.E)
>;END REPEAT
.E=.E-.N
>;END DEFINE

DEFINE	ELSECASE<
		JRST $LR(\.E)
IFL	.R,<
  $EC
>;END IFL
IFGE	.R,<
  $DL(\.N)
>;END IFGE
>;END DEFINE

DEFINE	ENDSEL<
IFL	.R,<
  $EC
>;END IFL
IFGE	.R,<
  $DC(\.N)
>;END IFGE
$DL(\.E)
$POP	.R,.N,.E
>;END DEFINE
DEFINE	LOOP<
$PUSH	.L
.L=.LBL
.LBL=.LBL+2
$DL	\.L
>;END DEFINE

DEFINE	WHILESKIP<
		JRST $LR(\<.L+1>)
>;END DEFINE

DEFINE	WHILE(TSTINS)<
		TSTINS .+2
		JRST $LR(\<.L+1>)
>;END DEFINE

DEFINE	UNTILSKIP<
		CAIA
		JRST $LR(\<.L+1>)
>;END DEFINE

DEFINE	UNTIL(TSTINS)<
		TSTINS $LR(\<.L+1>)
>;END DEFINE

DEFINE	EXITLOOP<
		JRST $LR(\<.L+1>)
>;END DEFINE

DEFINE	NEXTLOOP<
		JRST $LR(\.L)
>;END DEFINE

DEFINE	ENDLOOP(TSTINS)<
IFB	<TSTINS>,<
		JRST $LR(\.L)
>;END IFB
IFNB	<TSTINS>,<
		TSTINS $LR(\.L)
>;END IFNB
$DL	\<.L+1>
$POP	.L
>;END DEFINE

END