.TITLE HELLO ; Multiprocessor V5 JAN-85 ; To be run on user-processor ("satellite"). SY:HL.SYS should be installed! ; DATACOMM. HELP-PROGRAM, Shows counters, DEVICE LISTS, device STATUS&SIZE ; read/write PROTECTION SCHEME, checks remote DATE&TIME and MESSAGE exchange ; ************* NO user edits in this program ************* ;+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++; ; COPYRIGHT (c) 1985 by ; ; H.H. Klin. Neuro. AZG ; ; ; ; This software is furnished under a LICENSE and may be USED ONLY IN ; ; ACCORDANCE WITH THE TERMS OF SUCH LICENSE. 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. ; ; ; ;+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++; ; MAILBOX: message structure in file SY:JBINFO.DAT: ; -------- ; Block 0: DVLIST = Device list (RAD50 + ASCII) ; Block 1: STATUS, SIZE, JOBDEF list ; Block 2-8.: Boot blocks (=secundairy bootstrap program) for each job MAIL=9. ;Block start address of messages in mailbox ; ! Block #MAIL! Block +1 ! Block +2 ! Block +3 ! Block +4 ! ; !-------------!------------!------------!-----------!------------!---- ; ! common info ! message TO ! mess. FROM ! mess. TO ! mess. FROM ! ; ! for ALL jobs! JOB 0 ! JOB 0 ! JOB 1 ! JOB 1 ! etc. ; Att. * Received message is restricted to 480. bytes!! (16 words SYS-info) ; * HELLO should always read/write 1block(=256. words) at a time! .MCALL .EXIT, .PRINT, .LOOKUP,.READW,.WRITW,.CLOSE,.SETTOP .MCALL .GTLIN,.RCTRLO,.DATE, .TTYIN,.DSTAT,.FETCH,.RELEAS .MCALL .GTIM, .SDTTM, .SPFUN .ENABL LC .GLOBL TIME,TIMASC START:: MOV @#50,R5 ;Load R5 with high program limit. TST (R5)+ ;Make R5 point to free space .DSTAT #STAT,#FIL0 BCS 10$ TST STAT+4 ;Handler already loaded? BNE LOADED MOV STAT+2,R0 ;Handler size! ADD R5,R0 ;New high limit needed! BCS MEMOVR MOV R0,-(SP) .SETTOP R0 ;Do limit request. BCC 1$ TST (SP)+ .PRINT #SETERR .EXIT 1$: CMP R0,(SP)+ ;Enough memory? BCS MEMOVR .FETCH R5,#FIL0 BCC LOADED 10$: .PRINT #NOINST .EXIT MEMOVR: .PRINT #NOMEM .EXIT ; ; Open channel ; LOADED: .LOOKUP #AREA,#0,#FIL0 ;get MAILBOX of Remote Host BCS LFAIL0 JMP OK ; ; Error returns: ; LFAIL0: .PRINT #NOLK0 .EXIT ;----------------------------------- FIL0: .RAD50 /HL / .WORD 0 ;----------------------------------- STAT: .BLKW 4 NOINST: .ASCIZ /?HELLO-F-HL: not in SYSTEM/ NOMEM: .ASCIZ /?HELLO-F-Not enough memory!/ SETERR: .ASCIZ /?HELLO-F-.SETTOP error!/ NOLK0: .ASCIZ /?HELLO-F-HL: lookup failure/ IOERR: .ASCIZ \?HELLO-W-HL: I/O error!\ ALLTXT: .ASCII <12>/Remote News:/<015><012> .ASCIZ /------------/ YOUTXT: .ASCII /Message for you:/<015><012> .ASCIZ /----------------/ MSGTXT: .ASCII /Transmit message? Type>/<15><12> .ASCIZ /-----------------------/ ENDTXT: .ASCIZ /MESSAGE transmitted:/ .EVEN ;===========================================================================; OK: .READW #AREA,#0,#DVLIST,#256.,#0 ;Get DEVICE LIST BCS 1$ .READW #AREA,#0,#SIZTAB,#100.,#1 BCS 1$ .READW #AREA,#0,#BUFFER,#256.,#MAIL ;Read the news BCC 2$ 1$: JMP HRDERR ; ; Remote JOB info is in: #BUFFER+480. == IONRHI ; 482. ...490. == IONRLO,CHKERR,HRDERR,BUFSIZ,BLOCKS ; 492. ...498. == CHSTAT,RDSTAT,WTSTAT,JBSTAT ; 500. ...504. == DATE, TIME-HI, TIME-LO 2$: .DATE ;Local DATE MOV R0,LCDATE .GTIM #AREA,#LCTIME ;Local TIME ; ; Check DATE's ; TST JBDATE BNE 10$ .PRINT #NORDAT BR CONTIN ; 10$: TST LCDATE BNE 20$ .PRINT #NOLDAT BR 150$ ; 20$: CMP LCDATE,JBDATE BNE 100$ CMP LCTIME,JBTIME ;Compare High order time only. BEQ CONTIN 100$: .PRINT #DATDIF MOV JBDATE,R0 CALL DATASC MOV #RTIARG,R5 CALL TIMASC .PRINT #HDMESS ; MOV LCDATE,R0 CALL DATASC MOV #LTIARG,R5 CALL TIMASC .PRINT #HDMESS ; 150$: MOV #ARGYES,R5 ;Copy remote DATE&TIME? CALL QA CMPB #'Y,INPUT BEQ 160$ CMPB #'y,INPUT BNE CONTIN 160$: .READW #AREA,#0,#BUFFER,#256.,#MAIL ;Read again for actual time BCC 200$ JMP HRDERR 200$: .SDTTM #AREA,#JBDATE ; == #BUFFER+500. == Set remote date ; ; News and messages: ; CONTIN: .PRINT #ALLTXT .PRINT #BUFFER CLR R1 BISB JBSTAT,R1 ASL R1 ;Make block address INC R1 ; of message to us. ADD #MAIL,R1 .READW #AREA,#0,#BUFFER,#256.,R1 ;Read the message BCS HRDERR INC R1 MOV R1,WRTBLK CALL TTCR ;Wait for RETURN of keyboard .PRINT #YOUTXT .PRINT #BUFFER CALL TTCR ;Wait RETURN ; Show the remote system: ; ======================= CALL ACCNT CALL TTCR ;Wait RETURN CALL SHOWDV CALL TTCR ;Wait RETURN CALL SHOWRW CALL TTCR ;Wait RETURN ; Send a message to remote (G)host? ; ================================= .PRINT #MSGTXT ;Transmit message? MOV #DATA,BPOINT ;DATA=offset in BUFFER CLR NC ;Clear counter AGAIN: MOV #70.,NRCHAR ;Max. nr. chars / line MOV #ARGMES,R5 ;Set argument list for QA CALL QA ;Get a line CMPB #' ,INPUT ;1 st char a blank? BEQ FINISH ;No, go on! MOV #INPUT,R3 ;Inp. pointer MOV BPOINT,R2 ;outp. buffer pointer MOVB #12,(R2)+ ;Insert LF MOVB #15,(R2)+ ; and CR ADD #2,NC ;Count LF+CR MOV NRCHAR,R1 2$: MOVB (R3)+,(R2)+ ;move CMP R2,#LAST ;Buffer full? BHIS FINISH ;No->Ask for more input. INC NC SOB R1,2$ ; them MOV R2,BPOINT ; all BR AGAIN HRDERR: .PRINT #IOERR BR READY FINISH: MOV #TIMARG,R5 CALL TIME .DATE CALL DATASC ;Convert system date in R0 ; to ASCII string. MOV #BUFFER,R0 ;Copy Header into data buffer. MOV #HDMESS,R1 MOV #38.,R2 3$: MOVB (R1)+,(R0)+ SOB R2,3$ ; CLRB @BPOINT ;Set stringterminator INC NC ;Count 1 more for terminator ASR NC ;Nr. chars-> nr. words BEQ READY ;For no input. BCC 4$ INC NC INC BPOINT CLRB @BPOINT 4$: ADD #38.,NC ;For date and time header. .WRITW #AREA,#0,#BUFFER,NC,WRTBLK BCS HRDERR .PRINT #ENDTXT ;Yes, then exit .PRINT #BUFFER READY: .CLOSE #0 .RELEAS #FIL0 .EXIT ;-----------------------End of MAIN program---------------------------; ;=====================================================================; DVLIST: .BLKW 16.*4. MESSAG: .BYTE 0 MTCHAN: .BYTE 0 DVSTAT: .WORD 0 ;2nd device available mask! DASCII: .BLKW 190. SIZTAB: .BLKW 16.*2 RWSTAT: .BLKW 7.*2 JOBDEF: .BLKW 7.*2 .BLKW 40. DATDIF: .ASCIZ /Remote and local DATE&TIME differ:/ NORDAT: .ASCIZ /?HELLO-W-No REMOTE DATE!/ NOLDAT: .ASCIZ /?HELLO-W-No LOCAL DATE!/ .EVEN TIMARG: .WORD 0 .WORD TIMSTR LTIARG: .WORD 0 .WORD LCTIME .WORD TIMSTR RTIARG: .WORD 0 .WORD JBTIME .WORD TIMSTR WRTBLK: .WORD 0 ARGYES: .WORD 0 .WORD YES .WORD INPUT .WORD NRYES NRYES: .WORD 3 YES: .ASCIZ %Copy remote DATE&TIME? (Yes/No) [No]:% .EVEN ARGMES: .WORD 0 .WORD STRING .WORD INPUT .WORD NRCHAR STRING: .ASCIZ /?/ INPUT: .BLKB 70. ;1 LINE =70. bytes. NRCHAR: .WORD 70. AREA: .BLKW 10 ;Max. 8 arguments ;--------------------------------------------------------------------; HDMESS: .BYTE 12,11 ;LF, HORIZONTAL TAB .ASCII /Time / TIMSTR: .BLKB 8. ;1 .BYTE 40,40 DATSTR: .BLKB 17. .BYTE 12,12,15 ;HDMESS=date/time header= 38. bytes .WORD 0 ;HDMESS terminator ;--------------------------------------------------------------------; BPOINT: .WORD 0 NC: .WORD 0 ;===================================================; BUFFER: .BLKW 19. DATA: .BLKW 220. LAST: .WORD 0 ; Message Terminator IONRHI: .WORD 0 ; +480. IONRLO: .WORD 0 ; +482. CKSERR: .WORD 0 ; +484. COMERR: .WORD 0 ; +486. BUFSIZ: .WORD 0 ; +488. BLOCKS: .WORD 0 ; +490. CHSTAT: .WORD 0 ; +492. RDSTAT: .WORD 0 ; +494. WTSTAT: .WORD 0 ; +496. JBSTAT: .WORD 0 ; +498. JBDATE: .WORD 0 ; +500. JBTIME: .WORD 0,0 ;Ticks past midnight HIGH + LOW! ;===================================================; LCDATE: .WORD 0 LCTIME: .WORD 0,0 ;Ticks past midnight HIGH + LOW! .SBTTL DATASC ; ; R2=MONTH(1-12), R1=DAY(1-31), R3=YEAR(MODULUS 100) ; DATASC::MOV R0,R3 ;Convert system date in R0 to ASCII BEQ 1$ ;See Prog. Ref. 81-V4, pp. 2-26 BIC #^C37,R3 ADD #72.,R3 MOV R0,R1 ASL R1 ASL R1 ASL R1 SWAB R1 BIC #^C37,R1 MOV R0,R2 SWAB R2 ASR R2 ASR R2 BIC #^C37,R2 1$: MOV #DATSTR,R4 ;R4=date/tim pointer CALL CNVASC MOVB #' ,(R4)+ DEC R2 MOV R2,R1 ;*12. ASL R2 ASL R2 ASL R2 ASL R1 ASL R1 ADD R1,R2 MOV #MONTH,R1 ADD R2,R1 MOV #12.,R2 2$: MOVB (R1)+,(R4)+ SOB R2,2$ MOV R3,R1 CALL CNVASC RETURN MONTH: .ASCII /January 19/ .ASCII /February 19/ .ASCII / March 19/ .ASCII / April 19/ .ASCII / May 19/ .ASCII / June 19/ .ASCII / July 19/ .ASCII / August 19/ .ASCII /September 19/ .ASCII / October 19/ .ASCII /November 19/ .ASCII /December 19/ .EVEN CNVASC: CLR R0 DIV #10.,R0 ADD #'0,R0 ADD #'0,R1 CMPB R0,#'0 BNE 1$ MOV #' ,R0 1$: MOVB R0,(R4)+ MOVB R1,(R4)+ RETURN .SBTTL TTCR TTCR:: .PRINT #RET 1$: .TTYIN CMPB R0,#12 BNE 1$ RETURN RET: .ASCIZ <012>/Press RETURN to continue/ .EVEN ; ====================================================================; ; ---------------- Accounting & Remote Job Overview ------------------; ACCNT: .PRINT #HEAD1 ;Print account header (only once) .PRINT #HEAD2 CLR COUNT MOV #JOBDEF,R4 ;Set up JOB list pointer NEXTJB: MOV COUNT,R0 ADD #60,R0 MOVB R0,JBID TST (R4) ;End of list? BNE 1$ RETURN 1$: MOV #HDR50,R1 MOV (R4),R0 CALL R50ASC ;Convert physical JOB-handler name .PRINT #JBIDEN CMPB COUNT,JBSTAT BNE ACCFIN ; ; Print counters: ; MOV #IONRHI,R5 MOV (R5)+,R0 ;IOCNT HI MOV (R5)+,R1 ;IOCNT LO MOV #LINE,R3 ;Pointer to text field. CALL C10DBI MOVB #' ,(R3)+ MOV #4,R1 ;Further more 4 numbers. 2$: MOV (R5)+,R0 CALL CNVDEC SOB R1,2$ MOVB #200,@R3 ;Set stopper .PRINT #LINE ; ; Further job properties: ; ADD #6,R5 ;Skip CHSTAT, RDSTAT, WTSTAT BIT #100000,@R5 BEQ 6$ BIT #40000,@R5 BEQ 5$ .PRINT #BTSPD BR NXTLIN 5$: .PRINT #SPD BR NXTLIN ; 6$: BIT #40000,@R5 BEQ ACCFIN .PRINT #BT BR NXTLIN ACCFIN: .PRINT #CRLF NXTLIN: TST (R4)+ ; Skip vector TST (R4)+ ; Point to next INC COUNT JMP NEXTJB ; ----------------------ACCOUNT INFO---------------------- COUNT: .WORD 0 HEAD1: .BYTE 12 ;LF ;jbnam12345678901234567890 123456 123456 123456 123456 .ASCIZ / JOB Hndlr Nr. IO Checks Protoc Buffer No. / HEAD2: .ASCIZ / --- ----- requests errors errors size blocks/ BTSPD: .ASCIZ / BOOT & SPDIR code/ SPD: .ASCIZ / SPDIR, No BOOT/ BT: .ASCIZ / BOOT, No SPDIR/ JBIDEN: .ASCII / DCJOB/ JBID: .ASCII / (/ HDR50: .ASCII / )/<200> CRLF: .BYTE 0 .EVEN ; ============== SHOW Device names, status, size etc. =================; FILST$ = 100000 ; shows devicename (RAD50 representation), iden., size, status SHOWDV: .PRINT #HEADDV CLR COUNT MOV #DVLIST,R4 MOV #SIZTAB,R5 LOOP: CMP COUNT,#16. BLT 1$ RETURN ;Exit 1$: MOV #LINE,R1 ; ; Setup device no. ; MOV COUNT,R0 MOVB #' ,(R1) CMP R0,#9. BLOS 2$ MOVB #'1,(R1) SUB #10.,R0 2$: TSTB (R1)+ ADD #60,R0 MOVB R0,(R1)+ MOVB #' ,(R1)+ ; ; Setup device name: ; MOV (R4)+,R0 ;Device name CALL R50ASC MOVB #':,(R1)+ MOV (R4)+,R0 ;File name CALL R50ASC MOV (R4)+,R0 CALL R50ASC MOVB #'.,(R1)+ MOV (R4)+,R0 ;Extension CALL R50ASC MOV (R5)+,STATUS MOV #1,R2 ASH COUNT,R2 BIT R2,DVSTAT BNE IDEN ; No device: NODEV: MOVB #200,(R1) .PRINT #LINE .PRINT #PNODEV TST (R5)+ ;Skip last size JMP NEXT IDEN: CMP STATUS,#-1 BNE 2$ MOVB #' ,(R1)+ MOVB #' ,(R1)+ MOVB #' ,(R1)+ MOVB #'F,(R1)+ MOVB #'I,(R1)+ MOVB #'L,(R1)+ MOVB #'E,(R1)+ MOVB #' ,(R1)+ BR 10$ ; 2$: MOV #57,R0 ;No. of DEC "standard" devices MOV #DECLST,R2 3$: CMPB STATUS,R0 BEQ 5$ DEC R0 BPL 3$ ; ; NO "DEC" device, print iden. no. ; CLR R0 BISB STATUS,R0 MOV R1,R3 CALL CNVOCT MOV R3,R1 MOVB #' ,(R1)+ BR 10$ ; ; "DEC": ; 5$: ASL R0 ADD #DECLST,R0 MOVB #' ,(R1)+ MOVB #' ,(R1)+ MOVB #' ,(R1)+ MOVB #' ,(R1)+ MOVB #' ,(R1)+ MOVB (R0)+,(R1)+ MOVB (R0)+,(R1)+ MOVB #' ,(R1)+ ; ; Now print size: ; 10$: TST (R5)+ BIT #FILST$,STATUS ;Random access BEQ NOSIZ ; ; Variable size (SFFUN #300 => size unit 0, #301 => size unit 1, etc.): ; MOV #300,R3 ; Setup device size request for HL: handler ADD COUNT,R3 .SPFUN #AREA,#0,R3,#SIZE,#1,#BLK BCS 20$ MOV SIZE,R0 BR PSIZE 20$: MOV #SIZERR,R0 MOV #9.,R2 21$: MOVB (R0)+,(R1)+ SOB R2,21$ BR CHARAC NOSIZ: MOV #NOSIZE,R0 MOV #9.,R2 1$: MOVB (R0)+,(R1)+ SOB R2,1$ BR CHARAC ;------------------------ Print size in blocks ----------------------; PSIZE: MOV R1,R3 CALL CNVDEC MOV R3,R1 MOVB #'.,(R1)+ MOVB #' ,(R1)+ ; ; Check if file: ; CHARAC: CMP #-1,STATUS ; All bits up in status is file! BNE NOFILE ; File: MOVB #200,(R1) .PRINT #LINE .PRINT #PFILE NEXT: CMPB COUNT,MESSAG BNE 1$ .PRINT #FLAG1 BR 3$ 1$: CMPB COUNT,MTCHAN BNE 2$ .PRINT #FLAG2 BR 3$ 2$: .PRINT #CRLF 3$: INC COUNT JMP LOOP ; Print device properties: ; NOFILE: MOVB #' ,(R1)+ MOVB #' ,(R1)+ MOV #8.,R0 MOV #200,R3 MOV #DVP8,R2 PROP: BITB R3,STATUS+1 BEQ 30$ .REPT 5 MOVB (R2)+,(R1)+ .ENDR MOVB #' ,(R1)+ BR 31$ 30$: ADD #5,R2 31$: ASR R3 SOB R0,PROP ; MOVB #200,(R1) .PRINT #LINE BR NEXT STATUS: .WORD 0 SIZE: .WORD 0 BLK: .BLKW 4 DECLST: .ASCII /RKDTELLPTTDLDYPC10MTRFCTCR15DS17MMDPDXDM24NL262730/ .ASCII /313233DDMSPDPD40LSMQDRXT45LDVMDUSLDZDWPISPXL / DVP8: .ASCII /Filst/ DVP7: .ASCII /Ronly/ DVP6: .ASCII /Wonly/ DVP5: .ASCII /Specl/ DVP4: .ASCII /Hndlr/ DVP3: .ASCII /Spfun/ DVP2: .ASCII /Abtio/ DVP1: .ASCII /Varsz/ HEADDV: .ASCII <12>/No Remote Device iden. size characteristic/ .BYTE 12,0 PNODEV: .ASCII / ??/<11><11><200> PFILE: .ASCII / * File */<11><200> FLAG1: .ASCIZ <11>/ << Messages/ FLAG2: .ASCIZ <11>/ << Magtape/ SIZERR: .ASCII / Sizerr / NOSIZE: .ASCII / Nosize / .EVEN ;-------------- END SHOW Device names, status, size etc. -------------; ; =========================== SHOW R/W STATUS ============================; SHOWRW: .PRINT #HEADER .PRINT #UNLINE CLR R1 MOV #DASCII,R4 MOV #SHLIST,R3 REPEAT: MOV #1,R2 ASH R1,R2 MOVB #' ,OFFR(R3) MOVB #' ,OFFW(R3) MOVB #'N,OFFN(R3) BIT R2,CHSTAT ; Channel to handler OPEN? BEQ 3$ MOVB #'?,OFFN(R3) BIT R2,DVSTAT ; Drive "rotating"? BEQ 5$ MOVB #' ,OFFN(R3) ; Device O.K. ;---------- Read access? ------------ 5$: MOVB #'-,OFFR(R3) BIT R2,RDSTAT BEQ 2$ MOVB #'R,OFFR(R3) ;---------- Write access? ----------- 2$: MOVB #'-,OFFW(R3) BIT R2,WTSTAT BEQ 3$ MOVB #'W,OFFW(R3) 3$: .PRINT R4 .PRINT R3 ADD #OFFD,R4 ADD #OFFL,R3 INC R1 CMP R1,#16. BLO REPEAT .PRINT #UNLINE .PRINT #EXPL RETURN OFFD=21. OFFR=1. OFFW=7. OFFN=4. OFFL=11. HEADER: .ASCIZ /Remote device Access status/ UNLINE: .ASCIZ /-------------------------------/ SHLIST: .REPT 16. .ASCIZ / / ;10 spaces + 1 terminator .ENDR EXPL: .ASCII /R= read, W= write, N= no device/<15><12> .ASCIZ /?= disk not available? (removable?)/ .EVEN ; ============================ CONVERT ===============================; ; -----------------INTEGER TO ASCII CONVERSION------------ FORMAT=7. ;If defined gives number format ;--------------------------------------------------------- ; DouBle Integer to ASCII conversion: R0=high part, R1=Low part ; Max. value 32000K C10DBI::DIV #1000.,R0 MOV #7,FORM CALL CNV10 ;CONVERT RESULT MOVB #'K,(R3)+ MOV R1,R0 ;CONVERT REMAINDER MOV #4,FORM BR CNV10 ;--------------------------------------------------------- ; Integer to ASCII conversion(decimal): R0=value CNVDEC::MOV #FORMAT,FORM CNV10: MOV R2,-(SP) MOV #10.,R2 BR GO ;--------------------------------------------------------- ; Integer to ASCII conversion(octal): R0=value CNVOCT::MOV #FORMAT,FORM CNV8: MOV R2,-(SP) MOV #8.,R2 GO: MOV R4,-(SP) MOV R1,-(SP) .IIF DF FORMAT,CLR R4 CALL CONVRT CLRB @R3 MOV (SP)+,R1 MOV (SP)+,R4 MOV (SP)+,R2 RETURN CONVRT: MOV R0,R1 CLR R0 DIV R2,R0 MOV R1,-(SP) .IIF DF FORMAT,INC R4 TST R0 BEQ 1$ CALL CONVRT 1$: .IF DF FORMAT NEG R4 BEQ 30$ CMP R2,#8. BEQ 5$ DEC R4 5$: ADD FORM,R4 BLE 15$ 10$: MOVB #' ,(R3)+ SOB R4,10$ 15$: CMP R2,#8. BEQ 30$ 20$: MOVB #' ,(R3)+ 30$: .ENDC ; FORMAT MOVB (SP)+,@R3 BISB #'0,(R3)+ RETURN FORM: .WORD 0 ;--------------------------- RAD50 => ASCII -------------------------------; ; RAD50 to ASCII conversion routine ; R0 = RAD50 characters INPUT ; R1 > OUTPUT BUFFER ; R2 is USED as a SCRATCH register ; R50ASC: CALL DIV50 ; DIVIDE BY 50(8) MOV R2,-(SP) ; SAVE THIRD CHARACTER CALL DIV50 ; AGAIN MOV R2,-(SP) ; AND SAVE SECOND CHARACTER CALL DIV50 ; ONCE MORE CALL 10$ ; CONVERT TO ALPHA AND OUTPUT MOV (SP)+,R2 ; REMEMBER SECOND CALL 10$ ; AND OUTPUT MOV (SP)+,R2 ; REMEMBER THIRD ; AND FALL THROUGH 10$: TST R2 ; SPACE ? BEQ 20$ ADD #40,R2 ; NO - ADD OFFSET FOR A-Z CMP R2,#72 ; ALPHA ? BLE 20$ SUB #56,R2 ; NO - OFFSET TO NUMERIC CMP R2,#16 ; NUMERIC, *, OR % ? BGE 20$ CLR R2 ; NO - FORCE TO BLANK 20$: ADD #40,R2 ; FINISH TRANSLATION MOVB R2,(R1)+ ; AND OUTPUT RETURN ; ; DIV50 ROUTINE - DUMB SUBTRACT-AND-INCREMENT, BUT WHO CARES ; DIV50: MOV R0,R2 CLR R0 1$: SUB #50,R2 BCS 2$ INC R0 BR 1$ 2$: ADD #50,R2 RETURN ; =============================== QA ===================================; ; ; Subroutine for reading alpha-numeric input, see QUERY.MAC. ; CALL QA('Question',Logical array,Nr. of char. (max. 80)) ; QA:: 10$: MOV 2(R5),R2 ;Get address of question 20$: TSTB (R2)+ ;Determine length of question and make BNE 20$ ;string terminator octal 200 to suppress MOVB #200,-(R2) ;cariage return line feed MOV R2,R4 ;Save address of question string terminator BIS #40010,@#44 ;Lower case mode (bit 3 and 14 of JSW) .RCTRLO ;First entry also lower case ; ; Make up local answer string to display input field ; MOV @6(R5),R1 ;Get max. nr. of characters 30$: MOV #LINE,R2 ;Get address of local answer string 40$: MOVB #' ,(R2)+ ;Fill field with blanks SOB R1,40$ MOV R4,R3 ;Get address of quest. string term MOVB -(R3),(R2)+ ;Last char. of quest. is field delimiter MOVB #200,(R2) ;Field term. to suppress CR-LF .PRINT 2(R5) ;Print question .PRINT #LINE ;Print input field MOV @6(R5),R1 ;Get nr. of char. INC R1 ;Nr. of char. plus field delimiter MOV #LINE,R2 ;Get address of local answer string 50$: MOVB #10,(R2)+ ;Complete field with backspaces SOB R1,50$ .GTLIN #LINE,#LINE ;Print backspaces and read answer MOV #LINE,R2 CALL STRIP0 ;Strip leading, multiple and following ;blanks MOV @6(R5),R1 ;Max. permitted nr. of char. in answer MOV #LINE,R2 ;Get address of local answer string MOV 4(R5),R3 ;Get address of globle answer string clr r0 60$: MOVB (R2)+,(R3)+ ;Place local answer in globle string BEQ 70$ ;No (more) characters in local answer inc r0 SOB R1,60$ BR 90$ 70$: TSTB -(R3) ;Point to string terminator 80$: MOVB #' ,(R3)+ ;Complete globle string with blanks SOB R1,80$ 90$: mov r0,@6(r5) ;Nr. of chars in input TERMIN: CLRB @R4 ;Reset question string terminator RETURN ;Return to main program!! LINE: .BLKB 82. .SBTTL STRIP0 ; ; Subroutine to remove leading, multiple and following blanks ; ***** String terminator must be 0 ***** ; ; R2 should point to the begin of the string. ; On return R1 points to string terminator. ; STRIP0:: TSTB (R2) ;R2 is string pointer BEQ END2 ;No input MOV R2,R1 ;R1 is character replace pointer MOV R2,R3 ;Save begin address CMPB (R2)+,#' BEQ 25$ ;First character is blank, maybe more 10$: TSTB (R2) BEQ END2 ;Input is ok CMPB (R2)+,#' BNE 10$ ;Character is not a blank, continue MOV R2,R1 ;It's a blank save succeeding address TSTB (R2) BEQ END0 ;Found string terminator CMPB (R2)+,#' BNE 10$ ;Second char. is not a blank, continue 20$: TSTB (R2) BEQ END0 ;Reached end of string 25$: CMPB (R2)+,#' BEQ 20$ ;Found an other blank TSTB -(R2) ;Point to char. that succeeds blanks 30$: MOVB (R2),(R1)+ ;Replace character TSTB (R2)+ BEQ END1 ;Reached end of string CMPB (R2),#' BNE 30$ ;Found an other char. to be replaced MOVB (R2)+,(R1)+ ;Terminate replaced char. with a blank BR 20$ END0: CMP R3,R1 ;Compare with begin adderss BEQ END3 MOVB (R2),-(R1) ;Replace termin., delete last blank(s) RETURN END1: TSTB -(R1) ;R1 points to string terminator!! RETURN END2: MOV R2,R1 RETURN END3: MOVB (R2),(R1) ;Only blanks, string termin. is first char. RETURN .END START