; CL1VAL - CLONE INTERFACE TO VAL ; LAST EDIT: 31-OCT-81 ; .NLIST .LIST TTM .NLIST BEX .LIST .TITLE CL1VAL ; TEXT$ ON ; ; ; THIS MODULE CONTAINS THE INTERFACE TO VAL DATA STRUCTURES. ; IT SHOULD BE ASSEMBLED PRECDED BY VALMFD WHICH DEFINES ; OFFSETS IN VALCOM. IF THE VAL COMMON IS CHANGED THIS IS ; THE ONLY MODULE WHICH SHOULD REQUIRE MODIFICATION. ; ; ; ; THE PRINCIPAL ENTRY POINT IS RUNTSK WHICH GENERATES ; TRANSACTION STATII FOR THE CURRENT STREAM ACCORDING TO ; THE DEMANDS OF THE VAL REGION. ; IN ADDITION OTHER ENTRY POINTS MANIPULATE DATA IN THE TASK COMMON ; DISCON TO DISCONNECT A TASK FROM CLONE ; RPYTSK TO REPLY AN ITEM TO A TASK ; SEND TO SEND AN ACKNOWLEGEMENT TO A TASK ; ; THE FOLLOWING ROUTINES ARE CONTAINED IN OVERLAY SEGMENTS: ; STRTSK TO START A NEW TASK ; ALLESB TO ALLOCATE AN EXIT STATUS BLOCK FOR A TASK ; ; IMPORTANT VAL OFFSETS ARE: ; VC.FUN OPERATION FUNCTION CODE ; VC.CL1 CLONE LINKAGE. TASK STREAM ADDRESS ; VC.NAM VARIABLE NAME STRING ; VC.PRM REQUEST PROMPT STRING ; VC.STA VAL STATUS WORD ; VC.EFN LOCAL EFN TO SET ON COMPLETION ; VC.LBF TASK INPUT LINE BUFFER ; ; A TASK MAY SPECIFY THE FOLLOWING FUNCTIONS IN VC.FUN ; FU.CON CONNECT TASK TO CLONE ; FU.REQ NORMAL INPUT REQUEST ; FU.RTX TEXT INPUT REQUEST ; FU.TST TEST IF INPUT IS AVAILABLE ; FU.REC RECORD A VALUE ; FU.FIN NOTIFY CL1 OF TASK TERMINATION ; ; FOR INPUT REQUESTS THE TASK STREAM INTERPRETER CREATES ; A REQUEST DESCRIPTOR WHICH IS IN FACT A READIT BLOCK ; FOR THE STREAM AND PLACES IT IN THE STREAM ITEM. ; ; FOR CONNECT REQUESTS FROM A TASK THE CONTENTS OF ; THE INPUT BUFFER ARE QUEUED AS A NEW COMMAND. ; TEXT$ OFF ; ; .PSECT CL1VAL ; ; .MCALL CNCT$S ; ; ; VC.VAL=&177776 ;LOCATION FOR RECORDED VALUES. ; ; HERE WE FORCE CERTAIN VALCOM OFFSETS TO BE GLOBAL ; SO THAT ROUTINES ELSEWHERE MAY USE THEM. ; .GLOBL VC.CL1,VC.RTK,VC.STA,ST.CL1 ; ; ; ; RUNTSK - INTERPERATE A REQUEST FROM A TASK STREAM ; ; THIS ROUTINE CONNECTS THE TASK TO CLONE IF NOT ALREADY CONNECTED ; MAPS TO THE TASK COMMON REGION AND DISPATCHES TO THE APPROPRIATE ; FUNCTION PROCESSOR. ; ; RUNTSK::MOV STREAM,R1 ;GET TASK STREAM ADDRESS TST SL.ESB(R1) ;IS AN EXIT STATUS BLOCK ALLOCATED ? BNE 1$ MOV #EXTAST,R2 ;SET EXIT AST ADDRESS CALL ALLESB ;ALLOCATE AN EXIT STATUS BLOCK ADD #SL.TSK,R1 ;POINT TO TASK NAME CNCT$S R1,,R2 ;CONNECT TO TASK ; 1$: CALL MAP ;MAP OVER THE CURRENT STREAM REGION MOV STREAM,R0 ;GET BACK STREAM ITEM MOV VC.EFN(R1),SL.EFN(R0) ;SAVE EVENT FLAG ; CMP VC.FUN(R1),#FU.CON;CONNECT REQUEST ? BNE 10$ ; ; PROCESS A CONNECT REQUEST MOV R1,-(SP) ;SAVE ADDRESS OF COMMON MOV R1,R2 ;START ADDRESS OF COMMON ADD #VC.LBF+1,R2 ;START OF LINE BUFFER MOVB VC.LBF(R1),R1 ;GET BUFFER OFFSET ADD R1,R2 ;POINT TO START OF BUFFER CALL STRLEN ;GET LENGTH OF COMMAND STRING CALL STRLIT ;FORM A STRING LITERAL WITH IT MOV R0,R1 ;COPY ITEM ADDRESS MOV PROC,R0 ;GET CURRENT PROCESS MOV R1,PL.CBF(R0) ;QUEUE COMMAND TO PROCESS MOV (SP)+,R1 ;RESTORE ADDRESS OF COMMON MOV STREAM,VC.CL1(R1);SET STREAM POINTER BIS #ST.CL1,VC.STA(R1);SET CL1 CONNECT FLAG MOV #IS.SUC,VC.QST(R1);RETURN CONNECT STATUS MOV STREAM,R1 ;GET BACK STREAM POINTER MOV #TS.TSK,SL.STA(R1);SET STREAM STATUS CALL SEND ;LET TASK CONTINUE JMP 90$ ; ; PROCESS AN INPUT OR TEST REQUEST ; 10$: CMP VC.FUN(R1),#FU.REQ ;INPUT REQUEST ? BEQ 11$ CMP VC.FUN(R1),#FU.TST ;TEST REQUEST BNE 20$ ;MUST BE SOMETHING DIFFERENT ; 11$: MOV R1,R0 ;SAVE REGION POINTER ADD #VC.NAM,R1 ;POINT TO VARIABLE NAME STRING MOV R0,R2 ADD #VC.PRM,R2 ;POINT TO PROMPT STRING MOV #M.STR,R3 ;ASSUME THIS IS A STRING READ CMP VC.FUN(R0),#FU.TST ;BUT IS IT A TEST BNE 12$ CLR R3 ;IF SO SET TEST FLAG 12$: BIT #ST.ERR,VC.STA(R0) ;IS THIS TO BE A SPECIAL REQUEST ? BNE 13$ MOV R3,R0 CALL RQST ;DO A NORMAL INPUT REQUEST BR 90$ 13$: MOV R3,R0 CALL RQSTSP ;DO A SPECIAL INPUT REQUEST BR 90$ ; ; 20$: CMP VC.FUN(R1),#FU.FIN ;HAS TASK CALLED FINISH BNE 30$ MOV #IS.SUC,VC.QST(R1) ;RETURN OPERATION STATUS CMP VC.RTK(R1),#-1 ;IS IT RETURNING SOMEWHERE ? BNE 22$ ;IF SO DO NOTHING BIT #ST.CHN,VC.STA(R1) ;IS TASK CHAINING BEQ 21$ ;IF NOT DO FULL EXIT BIC #ST.CHN,VC.STA(R1) ;ELSE RESET CHAIN FLAG CALL DISESB ;DISCONNECT EXIT BLOCK BR 22$ ;AND RESUME TASK ; 21$: CALL DISCON BR 23$ ; 22$: MOV STREAM,R1 MOV #TS.TSK,SL.STA(R1) ;JUST FLAG STREAM RUNNING 23$: CALL SEND ;AND ACKNOWLEGE REQUEST BR 90$ ;NOTHING ELSE TO DO ; ; 30$: CMP VC.FUN(R1),#FU.REC ;IS THIS A RECORD REQUEST ? BNE 40$ ;SKIP IF NOT MOV R1,-(SP) ;SAVE REGION ADDRESS CMP VC.VAL(R1),#M.STR ;STRING ITEM ? BEQ 31$ MOV #5,R1 ;GET 5 WORD ITEM CALL GETSP MOV (SP),R1 ;RESTORE REGION ADDRESS MOV VC.VAL(R1),6(R0) ;SAVE MODE MOV VC.VAL+2(R1),10(R0) ;SAVE VALUE (INTEGER/BOOLEAN) BR 35$ ; 31$: MOV R1,R2 ;FORM STRING ADDRESS ADD #VC.VAL+2,R2 CALL STRLEN ;FIND LENGTH OF RECORD STRING CALL STRLIT ;AND FORM A STRING LITERAL MOV (SP),R1 ;RESTORE REGION ADDRESS ; 35$: CLR 4(R0) ;CLEAR OWNER ADD #VC.NAM,R1 ;POINT TO NAME STRING CALL RECORD ;RECORD ITEM IN STREAM MOV (SP)+,R1 ;RESTORE REGION ADDRESS MOV #IS.SUC,VC.QST(R1) ;RETURN COMPLETION STATUS MOV STREAM,R1 MOV #TS.TSK,SL.STA(R1) ;PUT TASK STREAM BACK IN RUN CALL SEND ;ACKNOWLEGE BR 90$ ; 40$: 90$: MOV PROC,R0 MOV STREAM,R1 RETURN ; ; ; DISCON - DISCONNECT CURRENT STREAM FROM A TASK ; INPUT: TASK STREAM CONTEXT ; OUTPUT: TASK REGION CONNECT FLAG IS CLEARED ; STREAM IS MARKED FOR EXIT ; R0=CURRENT PROCESS ; R1=CURRENT STREAM ; DISCON::CALL MAP ;MAP OVER REGION BIC #ST.CL1,VC.STA(R1) ;DISCONNECT TASK CALL DISESB ;DISCONNECT EXIT STATUS BLOCK MOV PROC,R0 MOV STREAM,R1 MOV #TS.EXT,SL.STA(R1) ;AND FLAG STREAM EXITED CALL DETREG ;AND DETACH REGION RETURN ; ; ; ; DISESB - DISCONNECT EXIT STATUS BLOCK ; ; THE EXIT STATUS BLOCK ASSOCIATED WITH A STREAM (IF ANY) ; IS DISCONNECTED FROM THE STREAM BY CLEARING ITS POINTER ; IN THE STREAM ITEM, AND THE STREAM POINTER IN THE ESB. ; THE ITEM ITSELF IS DE-ALLOCATED WHEN THE CONNECTED TASK ; EXITS. ; DISESB: MOV STREAM,R1 MOV SL.ESB(R1),R0 ;GET STATUS BLOCK ADDRESS BEQ 1$ ;SKIP IF ALREADY NULL CLR EB.STR(R0) ;CLEAR POINTER TO STREAM CLR SL.ESB(R1) ;CLEAR POINTER TO ESB 1$: RETURN ; ; ; ; RPYTSK - REPLY DATA TO A TASK ; INPUT: TASK STREAM CONTEXT ; OUTPUT: DATA IS COPPIED TO TASK BUFFER (EXCEPT TEST MODE) ; QIO STATUS BLOCK IS SET ; FOR TEST REQUEST: IS.SUC OR IE.EOF ; VALUE ITEM IS DE-ALLOCATED ; REQUEST DESCRIPTOR IS DEALLOCATED ; R0=CURRENT PROCESS ; R1=CURRENT STREAM ; ; REGISTERS DESTROYED: R2,R3 ; ; NB. THIS ROUTINE DOES NOT RE-ACTIVATE THE TASK ; SEND MUST BE CALLED TO COMPLETE THE REPLY. ; RPYTSK::MOV STREAM,R1 MOV SL.RQD(R1),R2 MOV R2,-(SP) ;SAVE REQUEST DESCRIPTOR CALL MAP ;MAP OVER TASK STREAM REGION TST RD.TYP(R2) ;IS THIS A TEST REQUEST BNE 10$ ;IF NOT SKIP ; ; REPLY TO A TEST FUNCTION MOV #IS.SUC,VC.QST(R1) ;ASSUME DATA AVAILABLE CLR VC.QST+2(R1) ;ZERO CHAR COUNT TST RD.BUF(R2) ;BUT IS THERE ANY ? BNE 20$ ; MOV #IE.EOF,VC.QST(R1) ;IF NOT RETURN EOF BR 20$ ; 10$: MOV R1,R3 ;POINT TO TASK BUFFER ADD #VC.LBF+1,R3 MOV RD.BUF(R2),R2 ;GET VALUE ITEM ADD #10,R2 ;SKIP HEADER CLR R4 ;INIT CHAR COUNT 11$: MOVB (R2)+,(R3)+ ;COPY STRING BEQ 12$ INC R4 BR 11$ 12$: MOV #IS.SUC,VC.QST(R1) ;SET QIO STATUS MOV R4,VC.QST+2(R1) ;RETURN CHAR COUNT TO STATUS MOVB R4,VC.LBF(R1) ;AND TO BUFFER MOV (SP),R2 ;GET REQUEST DESCRIPTOR MOV RD.BUF(R2),R0 ;GET VALUE ITEM CALL VOIDSP ;AND DE-ALLOCATE ; 20$: MOV (SP)+,R2 ;POP REQUEST DESCRIPTOR MOV R2,R0 ;AND DE-ALLOCATE CALL FREESP MOV STREAM,R1 MOV PROC,R0 CLR SL.RQD(R1) ;CLEAR DESCRIPTOR POINTER MOV #TS.RDY,SL.STA(R1) ;FLAG TASK READY RETURN ; ; ; ; SEND - SEND A TASK A MESSAGE SO IT CAN CONTINUE ; IN FACT WE JUST SET A LOCAL EVENT FLAG IN THE TASK ; ; INPUT: TASK STREAM CONTEXT ; ; NO REGISTERS MODIFIED ; SEND:: MOV R1,-(SP) MOV R2,-(SP) MOV R3,-(SP) MOV STREAM,R1 ;POINT TO TASK STREAM MOV R1,R3 ;OFFSET TO TASK NAME ADD #SL.TSK,R3 MOV SL.EFN(R1),R2 ;GET EFN CALL SETFLG ;SET CALLERS LOCAL EVENT FLAG MOV (SP)+,R3 MOV (SP)+,R2 MOV (SP)+,R1 RETURN ; ; ; DETREG - DETACH CURRENT STREAM REGION ; ; .END