.TITLE DINT -- DRIVING TABLE INTERPRETER .IDENT /01/ ; ;COPYRIGHT 1976, ROME AIR DEVELOPMENT CENTER, ;ROME, NEW YORK ; ;DESIGN REFERENCE: ARPA76-05,06 ; ;VERSION: 01 ; ;AUTHOR: PAUL M. CASHMAN MARCH, 1976 ; ; DINT - DRIVING TABLE INTERPRETER ; DINT ACCEPTS A COMMAND LANGUAGE SYNTAX (DEFINED WITH ; TH MARGOT MACROS) AND AN INPUT COMMAND LINE AND ; INFORMS THE CALLER WHETHER OR NOT THE INPUT FORMED A ; SYNTACTICALLY CORRECT COMMAND. DURING INTERPRETATION ; DINT PERFORMS ANY SEMANTIC PROCESSING SPECIFIED VIA ; THE MARGOT 'ACTION' MACRO. ; ;REVISION HISTORY: ; ; EQUATED SYMBOLS: ; CLRSNX=177400 ;MASK TO CLEAR SIGN EXTENSION BY MOVB LS0=100000 ;CONSTANT TO INDICATE OP.LS0 OP CODE LS2=140000 ;CONSTANT TO INDICATE OP.LS2 OP CODE RP2=040000 ;CONSTANT TO INDICATE OP.RP2 OP CODE ARGMSK=RP2 ;MASK TO SEPARATE ARG/ NO ARG OP CODES ; ; THE FOLLOWING ARE OFFSETS INTO THE PARAMETER BLOCK BUILT IN THE ; CALLER'S PROGRAM BY THE DINT$ MACRO. ; R2 ALWAYS POINTS TO THE DINT PARAMETER BLOCK. ; OLD.SP=0 ;SAVE AREA FOR SP ON ENTRY B$SYN=OLD.SP+2 ;BASE ADDR OF PSECT $SYNBT B$ACT=B$SYN+2 ;BASE ADDR OF PSECT $ACTBT $LNLTH==B$ACT+2 ;*GLOBAL* ADDR OF INPUT LINE LENGTH .RPCNT=$LNLTH+2 ;REPEAT/LIST COUNT .RPMIN=.RPCNT+2 ;REPEAT/LIST MINIMUM .RPMAX=.RPMIN+2 ;REPEAT/LIST MAXIMUM $ERPTR=.RPMAX+2 ;FARTHEST SCAN POINTER ON ERROR $INTLC=$ERPTR+2 ;INITIAL VALUE OF INTERPRET LOC PTR $SCNLC==$INTLC+2 ;*GLOBAL* INITIAL VALUE OF SCAN LOC PTR $BFLTH=$SCNLC+2 ;INTEGER (NOT ADDR): INPUT BUFFER LENGTH $PARL0==$BFLTH+2 ;*GLOBAL* FIRST WORD OF OUTPUT PARAMETER BLOCK $PARL2==$PARL0+2 ;*GLOBAL* SECOND WORD OF OUTPUT PARAMETER BLOCK $TELOP==$PARL2+2 ;*GLOBAL* TELNET OP CODE SAVE WORD $HSTLN==$TELOP+2 ;*GLOBAL* HOST NAME LENGTH $HSTRG==$HSTLN+2 ;*GLOBAL* HOST NAME STRING (16. BYTES) ; ; ; LOCAL DATA: ; ; NONE. ; ; ; GLOBAL DATA: ; ; NONE. ; LOCAL VARIABLES: ; ; .INTLC = INTERPRET LOCATION - THE PC FOR DINT. INITIALIZED ; TO THE ADDRESS OF THE FIRST BYTE OUTPUT IN THE EXPAN- ; SION OF THE 'SYNTAX' MACRO WHICH DEFINES THE TOP- ; LEVEL CONSTRUCT. ; R5 IS .INTLC. ; .SCNLC = SCAN LOCATION - THE ADDRESS OF THE NEXT INPUT CHAR. ; INITIALIZED TO THE ADDRESS OF THE FIRST INPUT CHARACTER. ; R4 IS .SCNLC. ; .FAILC = FAIL LOCATION - THE NEW INTERPRET LOCATION IF AN ; OPERATION FAILS. THIS IS UNINITIALIZED. ; R3 IS .FAILC. ; ; DINT PUSHES ITS DATA ON THE SYSTEM STACK IN THE ORDER ABOVE. ; OF COURSE, NOT EVERY ITEM IS STACKED EVERY TIME. TO INITIALIZE ; THE STACK, DINT PUSHES 0,0,-1 UPON ENTRY. ; ; DINT ASSUMES THAT THE INPUT COMMAND LINE ENDS IN A NULL. ; ; WHEN DINT RETURNS, THE CARRY BIT WILL BE SET FOR FAILURE AND ; CLEAR FOR SUCCESS. ; LOCAL MACROS: ; .MACRO PUSH,VAL ;PUSH VAL ONTO STACK MOV VAL,-(SP) .ENDM ; .MACRO RESTOR,LOC ;POP STACK INTO LOC MOV (SP)+,LOC .ENDM ; .MACRO POP ;POP STACK TST (SP)+ .ENDM ; .MACRO MAKEV$ ;ADVANCE .INTLC IF ODD INC R5 BIC #1,R5 .ENDM ; .MACRO GETC$,LOC ;MOVE NEXT CHAR INTO LOC ;AND ADVANCE .SCNLC MOVB (R4)+,LOC .ENDM ; .MACRO BKSCN$ ;BACK .SCNLC BY 1 CHAR DEC R4 .ENDM ; .MACRO CMPC$,LOC ;COMPARE LOC WITH .SCNLC ;AND ADVANCE .SCNLC MOVB (R4)+,-(SP) ;SAVE CHARACTER RAISE (SP) ;RAISE TO UPPER CASE CMPB LOC,(SP)+ ;COMPARE CHARS .ENDM ; .MACRO RAISE,LOC,?L ;RAISE A CHARACTER TO UPPER CASE CMPB LOC,#141 ;IF CHAR IS BETWEEN... BLT L CMPB LOC,#172 ;...LOWERCASE A-Z, BGT L BICB #40,LOC ;...THEN RAISE IT L: .ENDM DINT:: MOV SP,OLD.SP(R2) ;SAVE ENTRY VALUE OF SP .IRP REG, ;SAVE CALLER'S REGISTERS PUSH REG .ENDM PUSH #0 ;END VALUE FOR .INTLC MOV $INTLC(R2),R5 ;INITIALIZE .INTLC MOV $SCNLC(R2),R4 ;INITIALIZE .SCNLC PUSH R4 ;END VALUE FOR .SCNLC PUSH #-1 ;END VALUE FOR .FAILC ; ; RETURN HERE TO GET NEXT OPERATOR ; NEXTOP: MOVB (R5)+,R1 ;FETCH OPERATOR JMP.OP: JMP @BRTABL(R1) ;JUMP TO PARICULAR OPERATOR ; BRANCH TABLE OF DINT OP CODES ; .EVEN BRTABL: .WORD OP$ALL ;ALLOW .WORD OP$ALT ;ALTERN .WORD OP$CAA ;CALL ACTION (WITH ARGUMENTS) .WORD OP$CH0 ;CHARACTER (0 ARGS) .WORD OP$CH1 ;CHARACTER (1 ARG) .WORD OP$CH2 ;CHARACTER (2 ARGS) .WORD OP$CLA ;CALL ACTION (NO ARGUMENTS) .WORD OP$CLS ;CALL SYNTAX .WORD OP$EAF ;ENDALT FAIL .WORD OP$EAS ;ENDALT SUCCESS .WORD OP$EOF ;ENDOPT FAIL .WORD OP$EOS ;ENDOPT SUCCESS .WORD OP$ERF ;ENDREP FAIL .WORD OP$ERS ;ENDREP SUCCESS .WORD OP$ESF ;ENDSYN FAIL .WORD OP$ESS ;ENDSYN SUCCESS .WORD OP$FAO ;FAIL OPTION .WORD OP$FAR ;FAIL REPEAT .WORD OP$KEY ;KEYWORD .WORD OP$LS0 ;LIST (NO ARGUMENTS) .WORD OP$LS2 ;LIST (WITH ARGUMENTS) .WORD OP$NOP ;NO OPERATION .WORD OP$OPT ;OPTION .WORD OP$ORF ;OR FAIL .WORD OP$ORS ;OR SUCCESS .WORD OP$RP0 ;REPEAT (NO ARGUMENTS) .WORD OP$RP2 ;REPEAT (WITH ARGUMENTS) .WORD OP$REQ ;REQUIRE .WORD OP$STG ;STRING ENDBRT: .WORD OP$SYN ;SYNTAX ; ALL DINT OPERATORS RETURN HERE UPON COMPLETION OF THEIR PARTICULAR ; PROCESSING. IF FAILURE HAS OCCURRED, .INTLC IS -1; IF SUCCESS HAS ; OCCURRED, .INTLC IS ZERO. IF .INTLC IS NEITHER, WE CONTINUE WITH ; THE NEXT OP CODE. ; DINRET: TST R5 ;CHECK .INTLC BEQ CLEAN ;SUCCESS CMP #-1,R5 ;FAILURE? BNE NEXTOP ;NO - CONTINUE PROCESSING WITH NEXT OP ; CLEAN: MOV OLD.SP(R2),R1 ADD #-14,R1 CMP SP,R1 ;SP SHOULD POINT TO VALUE OF R5 STACKED ;BY DINT UPON ENTRY BEQ DINEXT ;STACK IS OK ; ; IF WE REACH HERE, STACK IS OUT OF WHACK. LOG ERROR AND NOTE FAILURE. ; MOV #-1,R5 ;FORCE FAILURE REMOVE: POP ;POP STACK CMP SP,R1 ;UNTIL WE REACH STACKED VALUE OF R5 BNE REMOVE ; ; DINT ALWAYS RETURNS TO CALLER FORM THIS POINT ; DINEXT: TST R5 ;'C' BIT CLEARED ON SUCCESS BEQ REGRST ;SUCCESS? SEC ;NO - SET 'C' TO NOTE FAILURE REGRST: .IRP REG, RESTOR REG .ENDM RTS PC ;RETURN TO CALLER ; 'SYNTAX' OP CODES: ; OP.CLS ; OP.SYN ; OP.ESF ; OP.ESS ; OP$CLS: MOV R5,R0 ;CALCULATE RETURN .INTLC INC R0 PUSH R0 PUSH R4 ;STACK .SCNLC PUSH R3 ;STACK .FAILC MOVB (R5),R5 ;GET WORD OFFSET OF ADDR OF SYNTAX ; (N.B. MOVB CAUSES SIGN EXTENSION) ASL R5 ;WORD OFFSET -> BYTE OFFSET ADD B$SYN(R2),R5 ;ADD $SYNBT BASE ADDR MOV (R5),R5 ;R5 <- ADDR OF CALLED SYNTAX OP JMP DINRET ; ; OP$SYN: MAKEV$ ;INSURE EVEN .INTLC TO GET ARGUMENT MOV (R5)+,R3 ;SET .FAILC TO OP.SYN ARGUMENT JMP DINRET ; ; OP$ESF: RESTOR R3 ;RESTORE .FAILC RESTOR R4 ;RESTORE .SCNLC POP ;POP .INTLC MOV R3,R5 ;RESUME INTERPRETING AT FAIL LOC JMP DINRET ; ; OP$ESS: RESTOR R3 ;RESTORE .FAILC POP ;POP .SCNLC RESTOR R5 ;RESTORE .INTLC JMP DINRET ; 'CHARAC' OP CODES: ; OP.CH0 ; OP.CH1 ; OP.CH2 ; 'ALLOW' AND 'REQUIRE' OP CODES: ; OP.ALL ; OP.REQ ; OP$CH0: JSR PC,SCAN ;GET NEXT CHAR OF INPUT BEQ F.CHAR ;COULDN'T GET IT JMP DINRET ;GOT IT ; ; ; OP$CH1: JSR PC,SCAN ;GET NEXT CHAR OF INPUT BEQ F.CHAR ;COULDN'T GET IT RAISE R0 ;RAISE TO UPPER CASE CMPB (R5)+,R0 ;GOT IT - IS IT = OP.CH1 ARGUMENT? BNE F.CHAR ;NO - FAIL JMP DINRET ; ; OP$CH2: JSR PC,SCAN ;GET NEXT CHAR OF INPUT BEQ F.CHAR ;COULDN'T GET IT RAISE R0 ;RAISE TO UPPER CASE CMPB R0,(R5)+ ;GOT IT - IS IT >= OP.CH2 ARG #1? BLT F.CHAR ;NO - FAIL CMPB R0,(R5)+ ;YES - IS IT <= OP.CH2 ARG #2? BGT F.CHAR ;NO - FAIL JMP DINRET ;YES - SUCCEED ; ; OP$ALL: JSR PC,SCAN ;GET NEXT CHAR OF INPUT BNE BLANK ;IF NULL, JMP DINRET ; WE'RE DONE BLANK: CMP #' ,R0 ;IF BLANK, BEQ OP$ALL ; KEEP SCANNING BKSCN$ ;ELSE BACK UP .SCNLC JMP DINRET ;AND RETURN ; ; OP$REQ: JSR PC,SCAN ;GET NEXT CHAR OF INPUT BEQ F.CHAR ;COULDN'T GET IT CMP #' ,R0 ;CHAR MUST BE BLANK BNE F.CHAR ;FAIL IF IT IS NOT BR OP$ALL ;ELSE SCAN UP TO FIRST NON-BLANK ; ; FAILURE RETURN FROM CHARAC OP CODES ; F.CHAR: MOV R3,R5 ;CONTINUE INTERPRETING AT FAIL LOC CMP R4,$ERPTR(R2) ;HAVE WE EXCEEDED OLD ERROR POINTER? BLE JMPDIN ;IF LE NO MOV R4,$ERPTR(R2) ;SET NEW ERROR POINTER JMPDIN: JMP DINRET ; ; SCAN SUBROUTINE - GET AN INPUT CHAR INTO R0 ; SCAN: GETC$ R0 ;GET CHAR INTO R0 BEQ NULLCH ;CHAR WAS NULL - END OF INPUT RTS PC ;NON-NULL CHAR WAS GOTTEN - RETURN NULLCH: BKSCN$ ;BACK UP .SCNLC TO POINT TO NULL TST R0 ;TO SET 'Z' BIT RTS PC ;AND RETURN ; 'STRING' AND 'KEYWORD' OP CODES: ; OP.STG ; OP.KEY ; OP$STG: MOVB (R5)+,R0 ;GET NEXT STRING CHAR BNE NTEOS ;HAVEN'T HIT END OF STRING JMP DINRET ;END OF STRING - SUCCESS NTEOS: CMPC$ R0 ;COMPARE WITH NEXT INPUT CHAR BEQ OP$STG ;CHARS MATCH - CONTINUE JMP F.CHAR ;NO MATCH - FAIL ; ; OP$KEY: MOVB (R5)+,R1 ;GET MIN REQUIRED MATCH LENGTH MOVB (R5)+,R0 ;GET OPTIONAL MATCH LENGTH REQLUP: DEC R1 ;DECREMENT # OF REQ. CHARS TO MATCH BLT GETOPT ;GOT ALL OF REQ. STRING - MATCH REST CMPC$ (R5)+ ;COMPARE STRING AND INPUT CHARS BEQ REQLUP ;MATCH - CONTINUE JMP F.CHAR ;NO MATCH IN REQ. STRING - FAIL GETOPT: BIC #CLRSNX,R0 ;CLEAR SIGN EXTENSION IN R0 ADD R5,R0 ;R0 <- NEXT OP CODE ADDR OPTLUP: MOVB (R5)+,R1 ;GET STRING CHAR BNE NTEOK ;NOT END OF KEYWORD JMP DINRET ;END OF KEYWORD - SUCCESS NTEOK: CMPC$ R1 ;COMPARE STRING AND INPUT CHARS BEQ OPTLUP ;MATCH - CONTINUE BKSCN$ ;NO MATCH - BACK UP .SCNLC MOV R0,R5 ;SET .INTLC TO NEXT OP ADDR JMP DINRET ;SUCCEED ; 'OR' OP CODES: ; OP.ORF ; OP.ORS ; OP$ORF: MOV 2(SP),R4 ;SET .SCNLC TO SAVED .SCNLC MAKEV$ ;INSURE EVEN .INTLC MOV (R5)+,R3 ;SET .FAILC TO OP.ORF ARGUMENT JMP DINRET ; ; OP$ORS: MAKEV$ ;INSURE EVEN .INTLC MOV (R5),R5 ;RESUME INTERPRETING AT SUCCESS LOC JMP DINRET ; 'ALTERN' AND 'OPTION' OP CODES: ; OP.OPT ; OP.EOF ; OP.EOS ; OP.ALT ; OP.EAF ; OP.EAS ; OP$OPT: ;SAME CODE FOR OP.OPT AND OP.ALT OP$ALT: PUSH R4 ;SAVE .SCNLC PUSH R3 ;AND .FAILC MAKEV$ ;INSURE EVEN .INTLC MOV (R5)+,R3 ;.FAILC <- ARGUMENT OF OP.OPT/ALT JMP DINRET ; ; OP$EOF: RESTOR R3 ;RESTORE .FAILC RESTOR R4 ;AND .SCNLC JMP DINRET ; ; OP$EAF: RESTOR R3 ;SAME AS OP.EOF RESTOR R4 MOV R3,R5 ;EXCEPT .INTLC <- FAIL LOCATION JMP DINRET ; ; OP$EOS: ;SAME SUCCESS CODE FOR OPT/ALT OP$EAS: RESTOR R3 ;RESTOR .FAILC POP ;POP .SCNLC INC R5 ;TO SKIP OVER FAILURE OP CODE JMP DINRET ; 'REPEAT' AND 'LIST' OP CODES: ; OP.RP0 ; OP.RP2 ; OP.LS0 ; OP.LS2 ; OP.ERF ; OP.ERS ; OP$LS0: MOV #LS0,R0 ;R0 INDICATES OP.LS0 OP BR REPOPS OP$LS2: MOV #LS2,R0 ;R0 INDICATES OP.LS2 OP BR REPOPS OP$RP0: CLR R0 ;R0 INDICATES OP.RP0 OP BR REPOPS OP$RP2: MOV #RP2,R0 ;R0 INDICATES OP.RP2 OP REPOPS: PUSH .RPCNT(R2) ;PUSH CURRENT COUNT,MIN,MAX PUSH .RPMIN(R2) PUSH .RPMAX(R2) PUSH R4 ;SAVE .SCNLC PUSH R3 ;AND .FAILC CLR .RPCNT(R2) ;COUNT <- 0 CLR .RPMIN(R2) ;MIN <- 0 MOV #77777,.RPMAX(R2) ;MAX <- 2**15-1 BIT #ARGMSK,R0 ;ARGUMENTS? BEQ RPORLS ;NO. PROCESS RP0/LS0. MOVB (R5)+,.RPMIN(R2);PICK UP MIN CLR .RPMAX(R2) MOVB (R5)+,.RPMAX(R2);AND MAX CMP #377,.RPMAX(R2) ;377 MEANS INFINITE REPEAT BNE RPORLS BIS #77400,.RPMAX(R2) ;SO MAKE MAX A BIG NUMBER RPORLS: MAKEV$ ;TO PICK UP ARGUMENTS TST R0 BGE REP ;REPEAT OP CODE TST (R5)+ ;LIST OP CODE - SKIP OVER BEGIN LOC MOV (R5),R3 ;PICK UP .FAILC NEW VALUE MOV -2(R5),R5 ;.INTLC <- LOOP BEGIN LOC JMP DINRET REP: MOV (R5)+,R3 ;REPEAT OP- SET .FAILC AND CONTINUE JMP DINRET ; ; OP$ERF: CLR R0 ;SWITCH TO NOTE IF COUNT < MIN CMP .RPCNT(R2),.RPMIN(R2) BGE CNTOK ;COUNT => MIN MOV #-1,R0 CNTOK: RESTOR R3 ;RESTORE .FAILC AND .SCNLC RESTOR R4 RESTOR .RPMAX(R2) ;RESTORE MAX,MIN,COUNT RESTOR .RPMIN(R2) RESTOR .RPCNT(R2) TST R0 ;IS COUNT <= MIN? BEQ ERFDON ;NO - SUCCESS MOV R3,R5 ;YES - FAIL ERFDON: JMP DINRET ; ; OP$ERS: INC .RPCNT(R2) ;INCREMENT REPEAT COUNT CMP .RPMIN(R2),.RPCNT(R2) ;IS MIN <= COUNT? BGT CNTOK1 MOV R4,2(SP) ;IF SO, SET SAVED .SCNLC TO CURRENT ;VALUE OF SCAN POINTER CNTOK1: MAKEV$ ;INSURE EVEN .INTLC CMP .RPMAX(R2),.RPCNT(R2) ;IS MAX <= COUNT BGT RPLOOP ;NO - KEEP LOOPING RESTOR R3 ;YES - RESTORE STACKED VALUES RESTOR R4 RESTOR .RPMAX(R2) RESTOR .RPMIN(R2) RESTOR .RPCNT(R2) ADD #3,R5 ;RESUME INTERPRETING AFTER OP.ERF JMP DINRET RPLOOP: MOV (R5),R5 ;RESUME INTERPRETING AT TOP OF LOOP MOV -2(R5),R3 ;PICK UP .FAILC FOR LOOP JMP DINRET ; 'ACTION' AND 'FAIL' OP CODES: ; OP.CLA ; OP.CAA ; OP.FAO ; OP.FAR ; 'NO OPERATION' OP CODE: ; OP.NOP ; OP$CLA: MOVB (R5)+,R1 ;R1 <- WORD OFFSET ASL R1 ;WORD -> BYTE OFFSET ADD B$ACT(R2),R1 ;ADD ACTION BRANCH TABLE BASE ADDR MOV (R1),R1 ;R1 <- ADDRESS OF ACTION CODE PUSH R5 ;FOR WHEN R5 IS RESTORED ON RETURN BR JSR.AC ;GO JUMP TO ACTION OP$CAA: MOVB (R5)+,R1 ;SAME AS FOR OP.CLA ASL R1 ADD B$ACT(R2),R1 MOV (R1),R1 MAKEV$ ;.INTLC POINTS TO ARGUMENT CNT MOV (R5),R0 ;R0 <- ARGUMENT COUNT ASL R0 ;R0 = NO. WORDS IN ARG LIST ADD #2,R0 ;R0 = NO. BYTES IN ARG LIST AND COUNT ADD R5,R0 ;R0 POINTS TO FIRST OP AFTER ARG LIST PUSH R0 ;SAVE RETURN .INTLC (R0) ON STACK JSR.AC: JSR PC,(R1) ;JUMP TO ACTION RESTOR R5 ;GET RETURN .INTLC BCC ACTDON ;LEAVE IF ACTION SUCCESSFUL MOV R3,R5 ;FAIL OTHERWISE ACTDON: JMP DINRET ; ; OP$FAO: ;SAME CODE FOR BOTH FAIL OP CODES OP$FAR: MAKEV$ ;INSURE EVEN .INTLC TO PICK UP WORD MOV (R5),R5 ;RESUME INTERPRETING AT FAIL LOC OP$NOP: JMP DINRET .END