; ; THIS SET OF MACROS IS DESIGNED TO PROVIDE SUPPORT FOR ; STRUCTURED PROGRAMMING ON A PDP11 RUNNING RSX11D. ; IT IS BASED ON A SET OF MACROS DEVELOPED AT DUKE UNIVERSITY, ; NORTH CAROLINA (SOFTWARE PRACTICE AND EXPERIENCE ) ; AS MODIFIED BY COMPUTING DEVICES COMPANY. ; ; MODIFIED AGAIN BY M. BLAKE-KNOX ; ; INVOKATION OF THE 'STRMACS' MACRO WILL 'MCALL' ALL NECESSARY ; MACROS AND DEFINE SEVERAL SYMBOLS APPROPRIATELY. ; ; THE MACRO .USE CONTROL USE OF JMP'S OR BRANCHES. ; USE ' .USE JUMPS' TO GENERATE JUMPS ; USE ' .USE BRANCHES' TO GENERATE BRANCHES ; ; ; THE SYMBOL .LIST CONTROLS LISTING OF GENERATED LABELS. ; IF .LIST=1, LABELS LISTED; IF .LIST=2 LABELS NOT LISTED. ; THE DEFAULT IS .LIST=0 (DON'T LIST LABELS) ; ; THE MACRO DEFINITIONS ARE DIVIDED INTO SEVERAL ; CATEGORIES: ; 1. INNER MACROS ; 1.1 GENLBL--GENERATE A LABEL ; 1.2 CHKBRS--DETERMINE IF CONDITIONAL USES THIS BRANCH ; 1.3 GENBRS--DETERMINE WHICH CONDITIONAL BRANCH TO USE ; 1.4 GENTST--GENERATE DECISION TEST CODE ; 1.5 GETLBL--RETRIEVE LABEL FOR A BLOCK ; 1.6 GOBAK--GENERATE BACKWARD TRANSFER FOR BLOCK ; 1.7 GOBR--BENERATE BRANCH FOR BLOCKS ; 1.8 GOJMP--BENERATE JUMP FOR BLOCK ; 1.9 PUTLBL--SAVE LABEL GENERATED FOR A BLOCK ; 1.10 PUTCSE--SAVE # CASE ELEMENTS FOR A CASE BLOCK ; 1.11 GETCSE--GET # CASE ELEMENTS LEFT IN A CASE BLOCK ; 1.12 NUMELM--GET # ARGUMENTS TO MACRO CALL ; 1.13 ASCLAB--GENERATE ASCII STRING FROM LABEL ; 1.14 IFCINR--GENERATE CODE FOR STRING COMPARISON ; ; 2. SELECTIVE BLOCK EXECUTION MACROS ; 2.1 IF[B)--SINGLE CONDITION TEST ; 2.2 IFC--CHARACTER STRING TEST ; 2.3 OR[B)--EXTENSION OF IF OR WHILE WITH LOGICAL OR ; 2.4 AND[B)--EXTENSION OF IF OR WHILE WITH LOGICAL AND ; 2.5 INBND[B)--INCLUSIVE BOUNDS CHECK ; 2.6 EXBND[B)--EXCLUSIVE BOUNDS CHECK ; 2.7 ELSE--DUAL CONDITION (TERMINATES 'IF' AND INITIATES ; 2.8 CASE[B)--ONE OF MANY BLOCK EXECUTION ; ; 3. REPETITIVE BLOCK EXECUTION MACROS ; 3.1 WHILE[B)--LEADING DECISION LOOP ; 3.2 FOR--INDEXED LOOP ; 3.3 REPEAT--INITIATES TRAILING DECISION LOOP ; 3.4 UNTIL[B)--TERMINATES TRAILING DECISION LOOP ; 3.5 END--TERMINATES BLOCKS (EXCEPT REPEAT) ; ; 5. MISCELLANEOUS ; 5.12 STRMACS--DECLARE ABOVE MACROS TO ASSEMBLER ; ;*************************************************************************** ; ; .PAGE .SBTTL DEFINITIONS--DEFINITIONS USED IN MACROS ;************************************************************************ ; DEFINITIONS AND THINGS ;************************************************************************* ; ; ; COMMONLY USED DEFINITIONS DEFAULT=-1 ; VALUE OF DEFAULT PARAMETERS ; ; STRMACS--DECLARE MACROS TO ASSEMBLER .MACRO STRMACS .MCALL GENLBL,CHKBRS,GENBRS,GENTST,GETLBL,GOBAK,GOBR,GOJMP,PUTLBL .MCALL PUTCSE,GETCSE,NUMELM,ASCLAB .BKBGN=0 .NEST=0 .CASE=0 .CASEL=0 .JUMP=0 .LIST=0 TPROOF=0 FPROOF=0 .ENDM STRMACS ; ; .PAGE .SBTTL INNERMACROS--MACROS USED TO DEFINE OTHER MACROS ;************************************************************************ ; INNER MACRO DEFINITIONS START HERE ;************************************************************************ ; ; ; GENERATE A LABEL ; GENLBL GENERATES A NUMBERED LABEL USED TO BEGIN AND END BLOCKS. .MACRO GENLBL X1 .IF GT,.LIST .LIST .IFTF .'X1: .IFT .NLIST .ENDC .ENDM GENLBL ; ; ; ; DETERMINE IF THIS CONDITIONAL ; 'CHKBRS' DETERMINES IF THIS PARTICULAR CONDITIONAL WAS USED ; BY CHECKING THE CONDITIONAL AGAINST A PARTICULAR CONDITIONAL ; IF IT WAS, A CONDITIONAL BRANCH IS GENERATED .MACRO CHKBRS X1,X2,X3,X4 .IF IDN,X1,X2 B'X3 .'X4 .IFFND=.IFFND+1 .ENDC .ENDM CHKBRS ; ; ; ; DETERMINE WHICH CONDITIONAL BRANCH WAS USED ; 'GENBRS' DETERMINES WHICH CONDITIONAL BRANCH WAS USED ; BY TRYING ALL POSSIBILITIES .MACRO GENBRS X1,X2 .IFFND=0 .IF LE,.JUMP CHKBRS X1,PL,MI,X2 CHKBRS X1,MI,PL,X2 CHKBRS X1,EQ,NE,X2 CHKBRS X1,NE,EQ,X2 CHKBRS X1,VC,VS,X2 CHKBRS X1,VS,VC,X2 CHKBRS X1,CC,CS,X2 CHKBRS X1,CS,CC,X2 CHKBRS X1,GE,LT,X2 CHKBRS X1,LT,GE,X2 CHKBRS X1,GT,LE,X2 CHKBRS X1,LE,GT,X2 CHKBRS X1,HIS,LO,X2 CHKBRS X1,LO,HIS,X2 CHKBRS X1,HI,LOS,X2 CHKBRS X1,LOS,HI,X2 CHKBRS X1,SETON,EQ,X2 CHKBRS X1,SETOFF,NE,X2 .IIF LE,.IFFND .ERROR ;UNRECOGNIZED CONDITION; .MEXIT .ENDC CHKBRS X1,SETON,NE,+6 CHKBRS X1,SETOFF,EQ,+6 .IF LE,.IFFND B'X1 .+6 .ENDC JMP .'X2 .ENDM GENBRS ; ; ; ; GENERATE A TEST COMPARISON ; GENTST IS CALLED BY OTHER MACROS TO GENERATE DECISION TEST CODE ; FOR BLOCK EXECUTION. ARGUMENT X0 IS EITHER <> OR TO ; INDICATE WHETHER WORD OR BYTE TESTING IS TO BE GENERATED. ; ARGUMENTS X1,X2,X3 ARE THE SAME AS PASSED TO THE CALLING MACRO. ; THE WORD FOLLOWING THE CODE GENERATED BY 'GENTST' SHOULD ; BE A JMP (NOT A BRANCH) TO THE FALSE FORK OF THE TEST. .MACRO GENTST X0,X1,X2,X3 .NCHR .COND, .IF GT,.COND-3 BIT'X0 X1,X3 .MEXIT .ENDC .IF NB,X1 .IF B,X3 TST'X0 X1 .IFF CMP'X0 X1,X3 .ENDC .IFF .IF NB,X3 TST'X0 X3 .ENDC .ENDC .ENDM GENTST ; ; GET THE LAST GENERATED LABEL ; GETLBL RETRIEVES A BLOCK LABEL VALUE FROM SYMBOL .NSTXX, ; WHERE XX IS THE NESTING LEVEL OF THE BLOCK .MACRO GETLBL X1,X2,X3 X2=.NST'X1 X3=.TYP'X1 .ENDM GETLBL ; ; GENERATE BACKWARD TRANSFER ; GOBAK GENERATES A BACKWARD JUMP OR BRANCH TO THE ARGUMENT ; ADDRESS VALUE .MACRO GOBAK X1 .IF LE,.-<.'X1>-254. BR .'X1 .IFF JMP .'X1 .ENDC .ENDM GOBAK ; ; GENERATE A BRANCH ; GOBR GENERATES A FORWARD BRANCH FOR BLOCKS .MACRO GOBR X1 BR .'X1 .ENDM GOBR ; ; GENERATE A "JMP" STATEMENT ; GOJMP GENERATES A JUMP TO THE ARGUMENT ADDRESS VALUE .MACRO GOJMP X1 .IF LE,.JUMP BR .'X1 .IFF JMP .'X1 .ENDC .ENDM GOJMP ; ; STACK A LABEL ; PUTLBL SAVE THE BLOCK LABEL VALUES IN SYMBOL NSTXX, WHERE ; XX IS THE NESTING LEVEL OF THE BLOCK .MACRO PUTLBL X1,X2,X3 .NST'X1=X2 .TYP'X1=X3 .ENDM PUTLBL ; ; SAVE # CASE ELEMENTS FOR CASE BLOCK ; PUTCSE SAVES THE # OF CASE ELEMENTS FOR THIS CASE BLOCK ; IN SYMBOL .CSLXX, WHERE XX IS THE CASE BLOCK NESTING LEVEL. .MACRO PUTCSE X1,X2 .CSL'X1=X2 .ENDM PUTCSE ; ; GET # CASE ELEMENTS LEFT IN CASE BLOCK ; GETCSE RETRIEVES THE # OF CASE ELEMENTS LEFT IN THIS CASE ; BLOCK .MACRO GETCSE X1,X2 X2=.CSL'X1 .ENDM GETCSE ; ; GET # ARGUMENTS TO MACRO CALL .MACRO NUMELM X1,X2,X3,X4,X5,X6,X7,X8,X9,X10,X11,X12 .NARG .ARGN .ENDM NUMELM ; ; ; GENERATE ASCII STRING FROM PASSED PARAMETER(S) .MACRO ASCLAB X1,X2 .ASCII <15><12>/ .'X1'----'X2' \ .EVEN .ENDM ASCLAB ; ; IFCINR: ; ; INNER MACRO USED TO GENERATE ACTUAL COMPARISON ; LOOP FOR AN IFC MACRO. RA,RB,RC ARE REGISTERS CONTAINING ; THE SOURCE, DESTINATION AND COUNT. IF RC IS NULL, ; LENGTH IS IMPLICITY SPECIFIED BY A TERMINATING 0. ; .MACRO IFCINR RA,RB,RC,?L1,?L2,?L3 .IF NB, BEQ L1 .IFF BR L3 .IFTF L2: CMPB (RA)+,(RB)+ BNE L1 .IFF L3: TSTB (RA) BNE L2 .IFT SOB RC,L2 .ENDC L1: .ENDM IFCINR ; ; ; .PAGE .SBTTL SELECTIVEMACROS--SELECTIVE BLOCK EXECUTION MACROS ;************************************************************************* ; SELECTIVE BLOCKEXECUTION MACROS START HERE ;*********************************************************************** ; ; ; ; ; SINGLE CONDITION TEST ; IF INITIATES AND 'IF' BLOCK. COMPARISONS AND BIT TESTING ; OCCUR USING STANDARD PDP-11 BRANCH MNEMONICS PLUS 'SETON' AND ; 'SETOFF' .MACRO IF X1,X2,X3 .BKBGN=.BKBGN+1 .NEST=.NEST+1 PUTLBL \.NEST,.BKBGN,2 GENTST <>,X1,X2,X3 GENBRS X2,\<.BKBGN+4000> .ENDM IF ; ; ; ; INITIATE 'IFB' BLOCK ; IFB IS SIMILIAR TO 'IF' EXCEPT THAT BYTES ARE CHECKED .MACRO IFB X1,X2,X3 .BKBGN=.BKBGN+1 .NEST=.NEST+1 PUTLBL \.NEST,.BKBGN,2 GENTST ,X1,X2,X3 GENBRS X2,\<.BKBGN+4000> .ENDM IFB .MACRO IFC A,COND,AA,NUM,WHERE .MCALL IF,IFCINR .IF IDN,WHERE,REGS .IIF NB, TST NUM IFCINR A,AA,NUM IF ,COND .IFF MOV %0,-(%6) MOV %1,-(%6) .NTYPE $$$A,A .IIF NE,$$$A-00 MOV A,%0 .NTYPE $$$AA,AA .IF NE,$$$AA-01 .IF EQ,$$$AA-00 MOV 2(%6),%1 .IFF MOV AA,%1 .ENDC .ENDC .IF NB, MOV %2,-(%6) .NTYPE $$$NUM,NUM .IF NE,$$$NUM-02 .IF EQ,$$$NUM-00 MOV 4(%6),%2 .IFF .IF EQ,$$$NUM-01 MOV 2(%6),%2 .IFF MOV NUM,%2 .ENDC .ENDC .IFF TST NUM .ENDC IFCINR %0,%1,%2 .IFF IFCINR %0,%1 .ENDC B'COND .+6 CLC BR .+4 SEC .IIF NB, MOV(%6)+,%2 MOV (%6)+,%1 MOV (%6)+,%0 IF ,CS .ENDC .ENDM IFC ; ; ; ; EXTENSION OF IF OR WHILE WITH LOGICAL AND ; ONE ORMORE 'AND' STATEMENTS CAN BE WRITTEN IMMEDIATELY AFTER ; AN 'IF' OR 'WHILE' TO GENERATE A SEQUENCE OF TESTS ; CONNECTED BY AND (ALL MUST BE TRUE BEFORE THE BLOCK IS ; EXECUTED). 'AND' DOES NOT GENERATE ADDITIONAL BLOCKS ; AND SHOULD NOT HAVE ITS OWN 'END' STATEMENT. ; COMPARISONS AND BIT TESTING OCCUR EXACTLY AS IN 'IF' ; STATEMENTS .MACRO AND X1,X2,X3 GENTST <>,X1,X2,X3 GENBRS X2,\<.BKBGN+4000> .ENDM AND ; ; ; EXTENTSION OF 'IF' OR 'WHILE' WITH LOGICAL ANDB ; ANDB IS EXACTLY LIKE AND EXCEPT ALL COMPARISONS AND ; TESTS USE BYTES INSTEAD OF WORD INSTRUCTIONS .MACRO ANDB X1,X2,X3 GENTST ,X1,X2,X3 GENBRS X2,\<.BKBGN+4000> .ENDM ANDB ; ; EXTENSION OF 'IF' OR 'WHILE' WITH LOGICAL OR ; ONE OR MORE 'OR' STATEMENTS CAN BE WRITTEN IMMEDIATELY AFTER AN ; 'IF' OR 'WHILE' TO GENERATE A SEQUENCE OF TESTS CONNECTED BY ; OR ( ANY CAN BE TRUE TO CAUSE BLOCK TO BE EXECUTED). 'OR' DOES ; NOT GENERATE AN ADDITIONAL BLOCK AND SHOULD NOT HAVE ITS OWN ; 'END'. ; COMPARISONS AND BIT TESTING ARE EXACTLY AS IN 'IF' STATEMENTS .MACRO OR X1,X2,X3 .BKBGN=.BKBGN+1 GOBR \.BKBGN GENLBL \<.BKBGN-1+4000> GETLBL \.NEST,.BKEND,.BKTYP .IF LE,.BKTYP PUTLBL \.NEST,.BKBGN,<.BKTYP-1> .IFF PUTLBL \.NEST,.BKBGN,.BKTYP .ENDC GENTST <>,X1,X2,X3 GENBRS X2,\<.BKBGN+4000> GENLBL \.BKBGN .ENDM OR ; ; ; EXTENSION OF 'IF' OR 'WHILE' WITH ORB ; ORB IS EXACTLY THE SAME AS 'OR' EXCEPT THAT ALL COMPARISONS ; AND TESTS USE BYTES INSTEAD OF WORDS .MACRO ORB X1,X2,X3 .BKBGN=.BKBGN+1 GOBR \.BKBGN GENLBL \<.BKBGN-1+4000> GETLBL \.NEST,.BKEND,.BKTYP .IF LE,.BKTYP PUTLBL \.NEST,.BKBGN,<.BKTYP-1> .IFF PUTLBL \.NEST,.BKBGN,.BKTYP .ENDC GENTST ,X1,X2,X3 GENBRS X2,\<.BKBGN+4000> GENLBL \.BKBGN .ENDM ORB ; ; ; INCLUSIVE BOUND CHECK ; 'INBND' IS AN INCLUSIVE BOUNDS CHECK I.E. THE BLOCK IS ; EXECUTED IF VARIABLE X2 IS WITHIN BOUNDS X1<=X2<=X3 .MACRO INBND X1,X2,X3 IF X1,LE,X2 AND X2,LE,X3 .ENDM INBND ; ; ; INCLUSIVE BOUNDS CHECK FOR BYTES ; 'INBNDB' IS EXACTLY THE SAME AS 'INBND' EXCEPT THAT IT ; USES BYTES .MACRO INBNDB X1,X2,X3 IFB X1,LE,X2 ANDB X2,LE,X3 .ENDM INBNDB ; ; ; EXCLUSIVE BOUNDS CHECK ; 'EXBND' IS AN EXCLUSIVE BOUNDS CHECK I.E. THE BLOCK IS ; EXECUTED IF VARIABLE X2 IS OUTSIDE THE BOUNDS X1>X2>X3 .MACRO EXBND X1,X2,X3 IF X1,GT,X2 OR X2,GT,X3 .ENDM EXBND ; ; ; EXCLUSIVE BOUNDS CHECK FOR BYTES .MACRO EXBNDB X1,X2,X3 IFB X1,GT,X2 ORB X2,GT,X3 .ENDM EXBNDB ; ; ; DUAL CONDITION TEST INITIATE 'ELSE' BLOCK ; 'ELSE' TERMINATES AN 'IF' BLOCK AND BEGINS AN ELSE BLOCK TO ; PROVIDE A DUAL CONDITION TEST FOR TH .MACRO ELSE .BKBGN=.BKBGN+1 GOJMP \<.BKBGN+4000> GETLBL \.NEST,.BKEND,.BKTYP GENLBL \<.BKEND+4000> PUTLBL \.NEST,.BKBGN,3 .ENDM ELSE ; ; ; ONE OF MANY BLOCK EXECUTION INITIATE 'CASE' BLOCK ; ; FORM: CASE I, ; WHERE I IS THE CASE # AND A,B,C,D ARE THE ; ADDRESSES OF THE RSPECTIVE CASE ELEMENTS ; IF I IS LESS THAN 1 OR GREATER THAN THE NUMBER OF CASES ; LISTED, THEN NO CASES ARE EXEUTED. EACH CASE ELEMENT SHOULD ; BE TERMINATED WITH AN 'END' AND ALL CASES IN THE CASE BLOCK ; SHOULD BE TERMINATED WITH AN ADDITIONAL 'END' TO END THE ; CASE BLOCK ITSELF. .MACRO CASE X1,X2 .BKBGN=.BKBGN+1 .NEST=.NEST+1 .CASE=.CASE+1 NUMELM X2 PUTCSE \.CASE,.ARGN PUTLBL \.NEST,.BKBGN,5 MOV X1,-(SP) BLE .+8. CMP #.ARGN,(SP) BGE .+8. TST (SP)+ GOJMP \<.BKBGN+4000> ASL (SP) ADD PC,(SP) MOV @(SP)+,PC .WORD X2 .ENDM CASE ; ; ; INITIATE 'CASEB' BLOCK ; CASEB IS EXACTLY THE SAME AS CASE EXCEPT THAT ALL ; COMPARISONS, TESTS, ETC. USE BYTES INSTEAD OF WORDS .MACRO CASEB X1,X2 .BKBGN=.BKBGN+1 .NEST=.NEST+1 .CASE=.CASE+1 NUMELM X2 PUTLBL \.NEST,.BKBGN,5 PUTCSE \.CASE,.ARGN MOVB X1,-(SP) BLE .+8. CMPB #.ARGN,(SP) BGE .+8. TSTB (SP)+ GOJMP \<.BKBGN+4000> ASLB (SP) CLRB 1(SP) ADD PC,(SP) MOV @(SP),PC .WORD X2 .ENDM CASEB ; ; ; LEADING DECISION LOOP INITIATE 'WHILE' BLOCK ; 'WHILE' USES STANDARD PDP-11 BRANCH MNEMONICS PLUS ; 'SETON' AND 'SETOFF' TO PROVIDE LEADING DECISION ; LOOPING STRUCTURE .MACRO WHILE X1,X2,X3 .NEST=.NEST+1 .BKBGN=.BKBGN+1 PUTLBL \.NEST,.BKBGN,0 GENLBL \.BKBGN GENTST <>,X1,X2,X3 GENBRS X2,\<.BKBGN+4000> .ENDM WHILE ; ; ; INITIATE 'WHILEB' BLOCK ; 'WHILEB' IS EXACTLY THE SAME AS 'WHILE' EXCEPT THAT ALL ; COMPARISONS, TESTS, ETC. USE BYTES INSTEAD OF WORDS .MACRO WHILEB X1,X2,X3 .NEST=.NEST+1 .BKBGN=.BKBGN+1 PUTLBL \.NEST,.BKBGN,0 GENLBL \.BKBGN GENTST ,X1,X2,X3 GENBRS X2,\<.BKBGN+4000> .ENDM WHILEB ; ; ; INDEXED LOOPING INITIATE 'FOR' BLOCK ; INCREASING ITERATIVE 'FOR' LOOP ; ; FORM: FOR A,B,C,D ; WHERE A IS THE INDEX (NOT AN IMMEDIATE OPERAND) ; B IS THE INITIAL VALUE OF THE INDEX ; C IS THE LIMIT ; D IS THE OPTIONAL INCREMENT (ASSUMED TO BE 1) ; ANY CHANGES TO THE LIMIT AND INCREMENT DURING THE LOOP ; EXECUTUIN WILL BE REFLECTED IN THE NEXT PASS THROUGH ; THE LOOP TEST ; THE INDEX IS ASSUMED TO BE A SIGNED PDP-11 INTEGER. C<=B ; SHOULD ALWAYS BE TRUE .MACRO FOR X1,X2,X3,X4 .BKBGN=.BKBGN+1 .NEST=.NEST+1 MOV X2,X1 .NARG .ARGN .IF LE,.ARGN-3 DEC X1 .IFF SUB X4,X1 .ENDC PUTLBL \.NEST,.BKBGN,1 GENLBL \.BKBGN .IF LE,.ARGN-3 INC X1 .IFF ADD X4,X1 .ENDC GENTST <>,X1,LE,X3 GENBRS LE,\<.BKBGN+4000> .ENDM FOR ; ; ; TRAILING DECISION LOOP INITIATE 'REPEAT' BLOCK ; 'REPEAT' REPEATS THE FOLLOWING BLOCK UNTIL THE ; CONDITION ON THE ASSOCIATED 'UNTIL' STATEMENT IS SATISFIED .MACRO REPEAT X1 .BKBGN=.BKBGN+1 .NEST=.NEST+1 PUTLBL \.NEST,.BKBGN,4 GENLBL \.BKBGN .ENDM REPEAT ; ; ; TERMINATE 'REPEAT' BLOCK ; 'UNTIL' TESTS CONDITIONS AND REPEATS PRECEDING 'REPEAT' ; BLOCK UNTIL THE CONDITION IS TRUE. .MACRO UNTIL X1,X2,X3 GETLBL \.NEST,.BKEND,.BKTYP .NEST=.NEST-1 GENTST <>,X1,X2,X3 GENBRS X2,\.BKEND .ENDM UNTIL ; ; ; TERMINATE 'REPEAT' BLOCK ; 'UNTILB' IS EXACTLY THE SAME AS 'UNTIL' EXCEPT THAT ALL ; COMPARISONS, TESTS, ETC. USE BYTES INSTEAD OF WORDS .MACRO UNTILB X1,X2,X3 GETLBL \.NEST,.BKED,.BKTYP .NEST=.NEST-1 GENTST ,X1,X2,X3 GENBRS X2,\.BKEND .ENDM UNTILB ; ; ; TERMINATE A BLOCK ; 'END' TERMINATES 'WHILE','FOR','ELSE',EXLIM,'INLIM' AND ; 'CASE'BLOCKS AND CASE ELEMENT BLOCKS. EACH TYPE OF ; BLOK HAS ITS OWN TYPE AS GIVEN BY THE VALUE OF SYMBOL ; .BKTYP AS FOLLOWS: ; .BKTYP TYPE OF BLOCK TO BE ENDED ; <0 WHILE EXTENDED WITH 'OR' STATEMENTS ; 0 WHILE ; 1 FOR ; 2 IF ; 3 ELSE ; 4 REPEAT (USES 'UNTIL' INSTEAD OF 'END' ; 5 CASE ; ; SYMBOL .BKEND HAS THE VALUE OF THE LAST BLOCK ENTERED ; AND IS REDUCED BY 1 AFTER EACH END STATEMENT. 'END' ; HAS ONE ARGUMENT TO ALLOW LABELS ON END STATEMENTS AS IN PL/1 ; SYMBOL .BKTYP HAS THE VALUE OF THE LAST BLOCK ENTERED AND IS ; USED TO DETERMINE WHAT CODE IS TO BE GENERATED. IN THE CASE ; OF AN 'OR' EXTENDING A 'WHILE', .BKTYP IS ALSO THE NEGATIVE ; OF THE COUNT OF 'OR'S EXTENDING THE WHILE ; SYMBOL .NEST HAS THE VALUE OF THE DEPTH OF THE CASE NESTING OF THE ; THE BLOCK LAST ENTERED ; SYMBOL .CASE HAS THE VALUE OF THE DEPTH OF THE 'CASE' NESTING OF ; THE LAST 'CASE' BLOCK ENTERED ; SYMBOLS .CSLXX HAVE THE VALUES OF THE NUMBER OF CASE ELEMENTS ; LEFT IN CASE LEVEL XX ; SYMBOL .CASEL HAS THE VALUE OF THE NUMBER OF CASE ELEMENTS AS ; IT IS REDUCED IN A CASE ELEMENT BLOCK ; SYMBOLS .XXXX ARE THE STATEMENT LABELS AT THE BEGINNING OF ; BLOCKS IF SUCH BLOCKS NEED LABELS ; SYMBOLS .4XXXX ARE THE STATEMENT LABELS AT THE END OF BLOCKS ; IF SUCH BLOCKS NEED LABELS ; SYMBOLS .NSTXX HOLD THE BLOCK STATEMENT LABEL NUMBER FOR BLOCK ; NESTING LEVEL XX ; SYMBOLS .TYPXX HOLD THE BLOCK TYPE NUMBER FOR THE BLOCK AT NESTI ; NESTING LEVEL XX ; ; NOTE THAT IF THE 'END' CLOSES A 'WHILE' BLOCK EXTENDED BY ONE ; OR MORE 'OR' STATEMENTS, THEN THE BLOCK TYPE VALUE (.BKTYP) IS ; NEGATIVE AND SHOWS HOW MANY INTERVENING LABELS AT THE CURRENT NEST ; LEVEL WERE GENERATED BY 'OR' EXTENSIONS. EACH 'OR' INCREASES ; THE BLOCK COUNT BY ONE (BUT NOT THE NEST LEVEL). THUS, IT IS ; NECESSARY TO REDUCE THE CURRENT BLOCK COUNT BY THE NUMBER OF 'OR'S ; EXTENDING THE 'WHILE' BLOCK. THE PROPER BLOCK LABEL VALUE ; TO REPEAT THE WHILE CAN BE DETERMINED BY ADDING THE NEGATIVE ; .BKTYP VALUE TO THE CURRENT BLOCK NUMBER IN .BKEND .MACRO END X1 GETLBL \.NEST,.BKEND,.BKTYP .NEST=.NEST-1 .IF LT,.NEST .ERROR ; TOO MANY 'END' STATEMENTS ; .MEXIT .ENDC .IF LE,.BKTYP GOBAK \<.BKEND+.BKTYP> GENLBL \<.BKEND+4000> .MEXIT .ENDC .IF EQ,.BKTYP-1 GOBAK \.BKEND GENLBL \<.BKEND+4000> .MEXIT .ENDC .IF LE,.BKTYP-3 GENLBL \<.BKEND+4000> .MEXIT .ENDC .IF EQ,.BKTYP-10 ADD @(SP),(SP) RTS PC .MEXIT .ENDC .IF EQ,.BKTYP-11 ADD #2,(SP) RTS PC .MEXIT .ENDC .IF EQ,.BKTYP-12 RTS PC .MEXIT .ENDC .IF EQ,.BKTYP-5 GETCSE \.CASE,.CASEL .IF EQ,.CASEL GENLBL \<.BKEND+4000> .CASE=.CASE-1 .MEXIT .IFF .NEST=.NEST+1 .CASEL=.CASEL-1 PUTCSE \.CASE,.CASEL GOJMP \<.BKEND+4000> .MEXIT .ENDC .ENDC .ENDM END ; ; ; .PAGE ; RESTORE ALL THE REGISTERS ; ; ; 'ASSERT'----ASSERT THAT STATEMENT IS TRUE ; 'ASSERT' PRINTS THE STATEMENT LABEL IF THE GIVEN CONDITIONAL ; IS TRUE ( IF TPROOF >= 1 ) OR FALSE ( IF FPROOF >= 1 ) ; FORM1: ASSERT X1,X2,X3 ; FORM2: ASSERT X1,X2 ; FORM3: ASSERT X2 ; WHERE X1,X3 ARE OPERANDS ; AND X2 IS A CONDITIONAL .MACRO ASSERT X1,X2,X3 .IF GT,TPROOF+FPROOF .NARG .ARGN GENLBL \.BKBGN+1 .IIF EQ,.ARGN-3 IF X1,X2,X3 .IIF EQ,.ARGN-2 IF X1,X2 .IIF EQ,.ARGN-1 IF X1 .IF GT,TPROOF QIO$S #IO.WLB,#6,#1,,,,<#10$,#15.> WTSE$S #1 BR 20$ 10$: ASCLAB \.BKBGN,TRUE 20$: .ENDC .IF GT,FPROOF ELSE QIO$S #IO.WLB,#6,#1,,,,<#10$,#15.> WTSE$S #1 BR 20$ 10$: ASCLAB \.BKBGN-1,FALSE 20$: .ENDC END .ENDC .ENDM ASSERT ; ; ; .MACRO ASSERB X1,X2,X3 .IF GT,TPROOF+FPROOF .NARG .ARGN GENLBL \.BKBGN+1 .IIF EQ,.ARGN-3 IFB X1,X2,X3 .IIF EQ,.ARGN-2 IFB X1,X2 .IIF EQ,.ARGN-1 IFB X1 .IF GT,TPROOF QIO$S #IO.WLB,#6,#1,,,,<#10$,#15.> WTSE$S #1 BR 20$ 10$: ASCLAB \.BKBGN,TRUE 20$: .ENDC .IF GT,FPROOF ELSE QIO$S #IO.WLB,#6,#1,,,,<#10$,#15.> WTSE$S #1 BR 20$ 10$: ASCLAB \.BKBGN-1,FALSE 20$: .ENDC END .ENDC .ENDM ASSERB ; ; ; ; PROVIDE 'END' PAIR CHECKING .MACRO ENDCHK .IIF GT,.NEST,.ERROR ; TOO FEW 'END' STATEMENTS ; .ENDM ENDCHK ; ; ; ; MACRO TO CONTROL USE OF BRANCHES OR JUMPS ; BY THE MACROS ; ; .MACRO .USE TYPE .IF IDN,TYPE,JUMPS .JUMP=1 .IFF .IF IDN,TYPE,BRANCHES .JUMP=0 .IFF .ERROR ;INVALID ARGUMENT .ENDC .ENDC .ENDM .USE