.TITLE RSUCMD .IDENT /V7.07/ ;***************************************************************** ; ; RSUCMD ; ; THIS MODULE OBTAINS THE COMMAND LINE FOR THE RSU COMMAND ; AND CHECKS IT FOR SYNTAX. THE OUTPUT FILE IS OPENED ; AND THE FDBS ARE SET UP FOR THE DESIRED INPUT FILES. ; ; VERSION: V7 OCTOBER 1981 ; ; ; STEVE THOMPSON ; SCHOOL OF CHEMICAL ENGINEERING ; OLIN HALL ; CORNELL UNIVERSITY ; ITHACA NY 14853 ; ; REVISION HISTORY ; ---------------- ; ; SMT777 27-OCT-81 THIS MODULE CREATED IN ADDING NEW FUNCTIONALITY ; TO THE RSU COMMAND. ; ; SMT782 6-NOV-81 ADDED THE /NA SWITCH ; ; SMT786 10-NOV-81 ADDED THE /PL SWITCH ; ; SMT788 13-NOV-81 ALLOW GMCR$ ERROR TO USE DEFAULT COMMAND LINE ; ; SMT791 16-NOV-81 ADDED THE /LI SWITCH ; ; SMT798 9-JAN-82 ALLOW SWITCHES IMMEDIATELY FOLLOWING COMMAND ; NAME WITHOUT AN INTERVENING SPACE ; ; SMT812 5-APR-82 CHANGED COMMAND NAME FROM RPT TO RSU ; ; SMT814 12-APR-82 LOWER CASE MESSAGES FOR RSX-11M V4.0 ; ; SMT816 15-APR-82 ADDED THE /MA SWITCH AND ALLOWED FOR RSUREP ; TO TYPE OUT THE COMMAND LINE ; ; SMT821 23-APR-82 CHANGED ENTRY POINT NAMES OF ACCOUNTING ; SUPPORT ROUTINES (SEE MODIFY.TXT) ; ; SMT832 30-AUG-82 ADDED THE /SA SWITCH ; ; SMT835 31-AUG-82 ADDED THE /GR SWITCH ; ;****************************************************************** .MCALL CSI$,CSI$SW,CSI$SV,CSI$ND .MCALL EXST$S,DIR$,GTIM$S .MCALL CSI$1,CSI$2 .MCALL OPEN$W,OPNS$R,FDOP$R CSI$ ; ; MACROS ; .MACRO PRINT MSG,MSGSZ MOV MSG,TIDPB+Q.IOPL .IF B MSGSZ MOV MSG'SZ,TIDPB+Q.IOPL+2 .IFF MOV MSGSZ,TIDPB+Q.IOPL+2 .ENDC DIR$ #TIDPB .ENDM ; ; ERROR MESSAGES ; .NLIST BEX .IIF DF AA$V40, .ENABL LC ERR1: .ASCII /RSU -- Dynamic memory initialisation failure/ ERR1SZ=.-ERR1 ERR2: .ASCII /RSU -- Command syntax error/ ERR2SZ=.-ERR2 ERR3: .ASCII /RSU -- Illegal switch/ ERR3SZ=.-ERR3 ERR4: .ASCII /RSU -- Open failure on output file/ ERR4SZ=.-ERR4 ERR5: .ASCII /RSU -- Ambiguous command/ ERR5SZ=.-ERR5 ERR6: .ASCII /RSU -- Illegal date format/ ERR6SZ=.-ERR6 ERR7: .ASCII "RSU -- /FU switch has invalid uic" ERR7SZ=.-ERR7 ERR8: .ASCII "RSU -- /NA switch has invalid name" ERR8SZ=.-ERR8 ERR9: .ASCII "RSU -- /SA switch has invalid account number(s)" ERR9SZ=.-ERR9 ; ; MONTHS OF YEAR TABLE ; MONTHS: .ASCIZ /JAN/ .ASCIZ /FEB/ .ASCIZ /MAR/ .ASCIZ /APR/ .ASCIZ /MAY/ .ASCIZ /JUN/ .ASCIZ /JUL/ .ASCIZ /AUG/ .ASCIZ /SEP/ .ASCIZ /OCT/ .ASCIZ /NOV/ .ASCIZ /DEC/ .EVEN CSIBLK: .BLKB C.SIZE ; CSI CONTROL BLOCK ; ; SWITCH DESCRIPTOR AND SWITCH VALUE DESCRIPTOR TABLES ; .EVEN SWTAB: CSI$SW FU,FUMSK,MASKW,,,FUTAB ; /FULL:G:M SWITCH CSI$SW LO,LOMSK,MASKW ; /LOAD SWITCH CSI$SW BE,BEMSK,MASKW,,,BETAB ; /BEFORE:DD-MMM-YY SWITCH CSI$SW AF,AFMSK,MASKW,,,AFTAB ; /AFTER:DD-MMM-YY SWITCH CSI$SW DA,DAMSK,MASKW,,,DATAB ; /DATE:DD-MMM-YY SWITCH CSI$SW SP,SPMSK,MASKW,,NEG ; /[NO]SPOOL SWITCH CSI$SW NA,NAMSK,MASKW,,,NATAB ; /NAME:LASTNAME SWITCH CSI$SW PL,PLMSK,MASKW,,NEG ; /[NO]PLOT SWITCH CSI$SW LI,LIMSK,MASKW,,NEG ; /[NO]LIST SWITCH CSI$SW MA,MAMSK,MASKW,,NEG ; /[NO]MASTER SWITCH CSI$SW SA,SAMSK,MASKW,,,SATAB ; /SA:AC1:AC2:AC3:AC4:AC5:AC6 SWITCH CSI$SW GR,GRMSK,MASKW,,NEG ; /[NO]GROUP SWITCH CSI$ND ; END OF SWITCH TABLE FUTAB: CSI$SV OCTAL,FUGRP,2 ; /FU:GROUP:MEMBER CSI$SV OCTAL,FUMEM,2 ; CSI$ND ; BETAB: CSI$SV ASCII,BEDATE,10. ; /BE:DD-MMM-YY CSI$ND ; AFTAB: CSI$SV ASCII,AFDATE,10. ; /AF:DD-MMM-YY CSI$ND ; DATAB: CSI$SV ASCII,DADATE,10. ; /DA:DD-MMM-YY CSI$ND ; NATAB: CSI$SV ASCII,NAME,15. ; /NA:NAME CSI$ND ; SATAB: CSI$SV OCTAL,SANUM1,2. ; /SA:AC1:AC2:AC3:AC4:AC5:AC6 CSI$SV OCTAL,SANUM2,2. ; CSI$SV OCTAL,SANUM3,2. ; CSI$SV OCTAL,SANUM4,2. ; CSI$SV OCTAL,SANUM5,2. ; CSI$SV OCTAL,SANUM6,2. ; CSI$ND ; BEDATE: .BLKB 10. ; /BE DATE FIELD AFDATE: .BLKB 10. ; /AF DATE FIELD DADATE: .BLKB 10. ; /DA DATE FIELD NULL: .WORD 0 ; NULL COMMAND FLAG CMDADR: .WORD 0 ; STARTING ADDRESS OF COMMAND LINE CMDSIZ: .WORD 0 ; SIZE OF COMMAND LINE $CMDEP:: ; ENTRY POINT ; ; INITIALISE DYNAMIC MEMORY ; MOV #FREEHD,R0 ; GET ADDRESS OF FREE MEMORY LISTHEAD CALL $INIDM ; INITIALISE DYNAMIC MEMORY BCC 5$ ; IF CC GOOD PRINT #ERR1 ; PRINT INITIALISATION FAILURE EXST$S #EX$SEV ; EXIT WITH SEVERE ERROR 5$: CALL FRESIZ ; SIZE FREE DYNAMIC MEMORY MOV R1,INISIZ ; AND SAVE THE RESULT ; ; SET DEFAULT OUTPUT FILENAME TO DDMMMYY.RSU ; MOV #OUTBUF,R0 ; GET ADDRESS OF TEMPORARY FILENAME BUFFER MOV #TIMBUF,R4 ; GET ADDRESS OF TIME PARAMETERS BUFFER GTIM$S R4 ; GET TIME INFORMATION MOV G.TIDA(R4),R1 ; GET DAY OF MONTH CMP R1,#10. ; DAY LESS THAN 10.? BGE 7$ ; IF GE NO MOVB #'0,(R0)+ ; YES, INSERT A ZERO CHARACTER 7$: CALL DE.CML ; FORMAT DAY AS ASCII DECIMAL MOV G.TIMO(R4),R1 ; GET MONTH OF YEAR DEC R1 ; CONVERT TO TABLE INDEX ASL R1 ; ASL R1 ; ADD #MONTHS,R1 ; CALL MV.STR ; INSERT MONTH TEXT MOV G.TIYR(R4),R1 ; GET YEAR CALL DE.CML ; FORMAT AS ASCII DECIMAL MOVB #SPA,(R0)+ ; ADD TWO MORE SPACES MOVB #SPA,(R0)+ ; MOV #OUTBUF,R0 ; RESET BUFFER ADDRESS CALL $CAT5 ; CONVERT CHARS. 1-3 TO RADIX-50 MOV R1,DEFOUT+N.FNAM ; STORE IN DEFAULT FILENAME BLOCK CALL $CAT5 ; REPEAT FOR CHARS. 4-6 MOV R1,DEFOUT+N.FNAM+2 ; CALL $CAT5 ; AND CHARS. 7-9 MOV R1,DEFOUT+N.FNAM+4 ; ; ; OBTAIN COMMAND LINE ; CLR NULL ; ASSUME A NON-NULL COMMAND STRING CLR CMDLEN ; SHOW A ZERO LENGTH COMMAND LINE DIR$ #GMCR ; GET COMMAND LINE BCS 22$ ; IF CS NONE THERE, USE DEFAULT COMMAND LINE CLR MASKW ; ASSUME JUST "RSU" TYPED MOV #CMDBUF,R0 ; SET ADDRESS OF COMMAND LINE BUFFER MOV $DSW,R1 ; GET LENGTH OF COMMAND MOV R1,CMDLEN ; AND SAVE IT 20$: CMPB (R0),#SPA ; LOOK FOR A SPACE BEQ 29$ ; IF EQ, FOUND IT (NOT PART OF COMMAND) CMPB (R0),#'/ ; OR FOR A SLASH BEQ 30$ ; IF EQ, FOUND ONE (PART OF COMMAND) INC R0 ; POINT TO NEXT CHARACTER DEC R1 ; ANY MORE CHARACTERS TO CHECK? BGT 20$ ; IF GT YES 22$: INC NULL ; SHOW A NULL COMMAND BR 54$ ; NO, JUST "RSU" TYPED 29$: INC R0 ; POSITION AT FIRST CHARACTER OF COMMAND 30$: MOV R0,CMDADR ; SAVE START ADDRESS OF COMMAND LINE MOV $DSW,R1 ; CALCULATE COMMAND LINE LENGTH ADD #CMDBUF,R1 ; SUB R0,R1 ; MOV R1,CMDSIZ ; SAVE SIZE OF COMMAND LINE ; ; CHECK BASIC SYNTAX OF COMMAND LINE ; CSI$1 #CSIBLK,CMDADR,R1 ; CHECK SYNTAX BCC 40$ ; IF CC, SYNTAX IS GOOD, GO TO PARSER 38$: PRINT #ERR2 ; COMMAND SYNTAX ERROR 39$: PRINT CMDADR,CMDSIZ ; PRINT COMMAND LINE EXST$S #EX$SEV ; EXIT WITH SEVERE ERROR 40$: ; REF. LABEL ; ; PARSE COMMAND LINE ; CSI$2 #CSIBLK,OUTPUT,#SWTAB ; PARSE OUTPUT FILE SPECIFICATION BCC 50$ ; IF CC GOOD 48$: PRINT #ERR3 ; ILLEGAL SWITCH BR 39$ ; 50$: BITB #,C.STAT(R0) ; MULTIPLE FILES OR WILD CARDS? BNE 38$ ; IF NE YES, SYNTAX ERROR CALL CHKDAT ; CHECK DATE SWITCHES BCC 52$ ; IF CC GOOD 51$: PRINT #ERR6 ; ILLEGAL DATE FORMAT BR 39$ ; 52$: FDOP$R #OUTFDB,,#CSIBLK+C.DSDS ; SET DATASET DESCRIPTOR ADDRESS 54$: OPEN$W #OUTFDB ; OPEN OUTPUT FILE BCC 60$ ; IF CC GOOD PRINT #ERR4 ; OUTPUT FILE OPEN ERROR CALL $FCSEP ; GIVE ERROR DETAILS EXST$S #EX$SEV ; EXIT WITH SEVERE ERROR 60$: BITB #FD.TTY,F.RCTL(R0) ; OUTPUT DEVICE A TERMINAL? BEQ 61$ ; IF EQ NO INCB TTYFLG ; YES, SET A FLAG BIC #SPMSK,MASKW ; AND SET /-SP 61$: TST NULL ; NULL COMMAND? BNE 62$ ; IF NE YES BITB #CS.EQU,CSIBLK+C.STAT ; INPUT FILE SPECIFIED? BEQ 62$ ; IF EQ NO CSI$2 #CSIBLK,INPUT,#SWTAB ; PARSE INPUT FILE SPECIFICATION BCS 48$ ; IF CS ILLEGAL SWITCH BITB #,CSIBLK+C.STAT ; MULTIPLE FILES OR WILD CARDS? BNE 38$ ; IF NE YES, ERROR CALL CHKDAT ; CHECK DATE SWITCHES BCS 51$ ; IF CS, ERROR ; ; CHECK FOR AMBIGUOUS COMMAND ; 62$: BIT #,MASKW ; ANY /LO SWITCHES SPECIFIED? BEQ 70$ ; IF EQ NO MOV MASKW,R1 ; YES, COPY MASK WORD BIC #LOCOMB,R1 ; ANY REPORTING SWITCHES SPECIFIED? BEQ 65$ ; IF EQ NO, COMMAND IS OK PRINT #ERR5 ; AMBIGUOUS COMMAND EXST$S #EX$SEV ; 65$: INCB REPFLG ; SHOW LOAD RUN REQUIRED BR 75$ ; AND CONTINUE ; ; PROCESS /NA SWITCH. ANY NULL BYTES SET UP BY .CSI2 ARE SET TO SPACES ; 70$: BIT #NAMSK,MASKW ; /NAME SWITCH SPECIFIED? BEQ 74$ ; IF EQ NO TSTB NAME+14. ; NAME TOO LONG? BEQ 72$ ; IF EQ NO 71$: PRINT #ERR8 ; ILLEGAL /NA VALUE JMP 39$ ; 72$: TSTB NAME ; NAME SPECIFIED? BEQ 71$ ; IF EQ NO, BAD NEWS MOV #NAME,R0 ; SET ADDRESS OF NAME FIELD MOV #14.,R2 ; AND ITS MAXIMUM LENGTH 73$: TSTB (R0)+ ; NULL BYTE? BNE 731$ ; IF NE NO MOVB #SPA,-1(R0) ; YES, MAKE IT A SPACE 731$: DEC R2 ; MORE TO LOOK AT? BGT 73$ ; IF GT YES, LOOP ; ; PROCESS /SA SWITCH ; 74$: BIT #SAMSK,MASKW ; /SA SWITCH SPECIFIED? BEQ 742$ ; IF EQ NO CALL CHKSAS ; CHECK SWITCH VALUES BCC 742$ ; IF CC GOOD PRINT #ERR9 ; INVALID ACCOUNT NUMBER(S) JMP 39$ ; 742$: ; REF. LABEL ; ; PROCESS /FU SWITCH ; BIT #FUMSK,MASKW ; REPORT: IS /FU SPECIFIED? BEQ 75$ ; IF EQ NO CALL CHKUIC ; CHECK UIC GIVEN WITH /FU BCC 75$ ; IF CC GOOD PRINT #ERR7 ; ILLEGAL UIC JMP 39$ ; 75$: BIT #DAMSK,MASKW ; /DA SWITCH PRESENT? BEQ 76$ ; IF EQ NO BIC #,MASKW ; YES, IGNORE /AF AND /BE 76$: TST NULL ; NULL COMMAND? BNE 86$ ; IF NE YES, RETURN ; ; DETERMINE PROPER FDB ADDRESS FOR INPUT FILE AND SET UP DATASET DESCRIPTOR ; BITB #CS.EQU,CSIBLK+C.STAT ; INPUT SPEC. PRESENT? BEQ 86$ ; IF EQ NO MOV #$RFFDB,R0 ; ASSUME A REPORT IS REQUIRED TSTB REPFLG ; IS A REPORT REQUIRED? BEQ 80$ ; IF EQ YES MOV #$SFFDB,R0 ; ELSE SHOW A LOAD PLOT REQUIRED 80$: MOV F.DSPT(R0),R0 ; GET ADDRESS OF DATASET DESCRIPTOR MOV #CSIBLK,R1 ; SET ADDRESS OF CSI CONTROL BLOCK BITB #CS.DVF,C.STAT(R1) ; DEVICE FIELD SPECIFIED? BEQ 82$ ; IF EQ NO MOV C.DEVD(R1),(R0) ; SET LENGTH/ADDRESS OF DEVICE SPEC. MOV C.DEVD+2(R1),2(R0) ; 82$: BITB #CS.DIF,C.STAT(R1) ; DIRECTORY FIELD SPECIFIED? BEQ 84$ ; IF EQ NO MOV C.DIRD(R1),4(R0) ; SET LENGTH/ADDRESS OF DIRECTORY STRING MOV C.DIRD+2(R1),6(R0) ; 84$: BITB #CS.NMF,C.STAT(R1) ; FILENAME FIELD SPECIFIED? BEQ 86$ ; IF EQ NO MOV C.FILD(R1),10(R0) ; SET LENGTH/ADDRESS OF FILENAME STRING MOV C.FILD+2(R1),12(R0) ; 86$: RETURN ; RETURN TO ROOT ;+ ; *** CHKSAS ; ; THIS ROUTINE VALIDATES THE ACCOUNT NUMBERS GIVEN WITH THE /SA ; SWITCH. ZERO IS EQUIVALENT TO NO VALUE SPECIFIED. ; ;- CHKSAS: MOV #SANUM1,R0 ; SET ADDRESS OF FIRST SWITCH VALUE MOV #6,R1 ; SET NUMBER OF VALUES 10$: TST (R0)+ ; NEGATIVE VALUE (MASTER FLAG SET?) BLT 20$ ; IF LT YES, ILLEGAL VALUE DEC R1 ; ANY VALUES LEFT TO CHECK? BGT 10$ ; IF GT YES, LOOP CLC ; SHOW ALL VALUES OK BR 30$ ; RETURN 20$: SEC ; SHOW AN ILLEGAL VALUE SOMEWHERE 30$: RETURN ; RETURN TO CALLER ;+ ; *** CHKUIC ; ; THIS ROUTINE VALIDATES THE UIC GIVEN WITH THE /FU SWITCH. ZERO ; VALUES ARE EQUIVALENT TO WILD CARDS AND ARE LEGAL. ; ;- CHKUIC: MOV FUGRP,R0 ; GET GROUP CODE CALL 50$ ; CHECK IT BCS 10$ ; IF CS, ERROR MOV FUMEM,R0 ; GET MEMBER CODE CALL 50$ ; 10$: RETURN ; RETURN 50$: TST R0 ; CHECK FOR ZERO OR NEGATIVE VALUES BLT 60$ ; IF LT, ERROR BEQ 70$ ; IF EQ, OK CMP R0,#377 ; VALUE TOO HIGH? BLOS 70$ ; IF LOS, NO 60$: SEC ; ERROR RETURN ; 70$: CLC ; VALUE CHECKS OUT RETURN ; ;+ ; *** CHKDAT ; ; THIS ROUTINE IS CALLED TO CHECK THAT ANY DATE SWITCHES SPECIFIED ; HAVE A LEGAL SWITCH VALUE. CONVERSION OF DATES TO INTERNAL FORMAT ; IS ALSO DONE BY THIS ROUTINE. ; ;- CHKDAT: CLC ; INITIALISE TO CARRY CLEAR BIT #BEMSK,MASKW ; /BE SWITCH SPECIFIED? BEQ 10$ ; IF EQ NO MOV #BEDATE,R0 ; SET ADDRESS OF DATE FIELD MOV #BEDAY,R5 ; AND INTERNAL CONTROL BLOCK CALL CVTDAT ; CONVERT DATE BCS 30$ ; IF CS, ERROR 10$: BIT #AFMSK,MASKW ; /AF SWITCH SPECIFIED? BEQ 20$ ; IF EQ NO MOV #AFDATE,R0 ; SET ADDRESS OF DATE FIELD MOV #AFDAY,R5 ; AND INTERNAL CONTROL BLOCK CALL CVTDAT ; CONVERT DATE BCS 30$ ; IF CS, ERROR 20$: BIT #DAMSK,MASKW ; /DA SWITCH SPECIFIED? BEQ 30$ ; IF EQ NO MOV #DADATE,R0 ; SET ADDRESS OF DATE FIELD MOV #DADAY,R5 ; AND INTERNAL CONTROL BLOCK TSTB (R0) ; /DA DATE FIELD DEFAULTED? BNE 25$ ; IF NE NO MOV TIMBUF+G.TIDA,(R5)+ ; YES, SET TODAY'S DATE MOV TIMBUF+G.TIMO,(R5)+ ; MOV TIMBUF+G.TIYR,(R5)+ ; CLC ; SHOW EVERYTHING OK BR 30$ ; AND RETURN 25$: CALL CVTDAT ; CONVERT DATE 30$: RETURN ; RETURN TO CALLER ;+ ; *** CVTDAT ; ; THIS ROUTINE IS CALLED TO VERIFY THAT THE ASCII STRING GIVEN ; AS THE DATE IS IN FACT A LEGAL DATE. THE CONVERTED ; BINARY VALUES OF DAY/MONTH/YEAR ARE SET UP FOR USE BY OTHER ; ROUTINES. NOTE THAT WE DO NOT CHECK WHETHER THE VALUES ARE ; SENSIBLE, BUT JUST THAT THEY FITTHE DD-MMM-YY FORMAT. ; ; INPUT: ; R0 ADDRESS OF ASCII DATE FIELD ; R5 ADDRESS OF BINARY DATE BLOCK ; ; OUTPUT: ; CC DATE WAS LEGAL ; CS DATE ILLEGAL ; R0-R3 USED ; ;- CVTDAT: TSTB (R0) ; ANY DATE SPECIFIED? BEQ 45$ ; IF EQ NO, ERROR TSTB 11(R0) ; DATE STRING TOO LONG? BNE 45$ ; IF NE YES MOV #3,R3 ; SET NUMBER OF PLACES TO LOOK AT CALL 60$ ; GET BINARY DAY MOV R1,(R5) ; SAVE SPECIFIED DAY BEQ 45$ ; IF ZERO, THINGS ARE BAD CMP (R5)+,#31. ; IS DAY GREATER THAN 31.? BGT 45$ ; IF GT YES, ERROR CMPB R2,#<<'->-<'0>> ; DID DAY END WITH A HYPHEN? BNE 45$ ; IF NE NO, ERROR 7$: MOV #MONTHS,R1 ; GET ADDRESS OF MONTH TABLE MOV #1,-(SP) ; INITIALISE MONTH COUNT ON STACK MOV R0,-(SP) ; SAVE ASCII MONTH ADDRESS 10$: CMPB (R0)+,(R1)+ ; SAME MONTH? BNE 20$ ; IF NE NO TSTB (R1) ; YES, END OF MONTH? BNE 10$ ; IF NE NO, LOOP TST (SP)+ ; YES, CLEAR ADDRESS FROM STACK MOV (SP)+,(R5)+ ; AND SET MONTH UP BR 30$ ; THAT'S IT 20$: TSTB (R1)+ ; FIND END OF MONTH BNE 20$ ; (IT'S AN ASCIZ STRING) MOV (SP),R0 ; RESET ADDRESS OF ASCII MONTH STRING INC 2(SP) ; AND SHOW ONE MORE MONTH LOOKED AT TSTB (R1) ; LOOKED AT ALL MONTHS? BNE 10$ ; IF NE NO, LOOP CMP (SP)+,(SP)+ ; YES, CLEAN THE STACK BR 45$ ; AND SHOW AN ERROR 30$: CMPB (R0)+,#'- ; LEGAL SEPARATOR? BNE 45$ ; IF NE NO, ERROR MOV #2,R3 ; SET NUMBER OF PLACES TO LOOK AT CALL 60$ ; GET BINARY YEAR MOV R1,(R5)+ ; SAVE SPECIFIED YEAR BGT 50$ ; IF GT IT WAS OK 45$: SEC ; SET CARRY TO INDICATE ERROR 50$: RETURN ; ; ; ROUTINE TO CONVERT ASCII NO. TO BINARY FOR DATE CONVERSION ; 60$: CLR R1 ; ZERO THE TOTAL ACCUMULATOR 65$: MOVB (R0)+,R2 ; GET NEXT DIGIT BEQ 70$ ; IF EQ A NULL BYTE, END OF STRING SUB #'0,R2 ; SUBTRACT CHARACTER BIAS BLT 70$ ; IF LT, TOO SMALL CMP R2,#9. ; VALUE TOO LARGE? BGT 70$ ; IF GT YES ASL R1 ; MUTIPLY PREVIOUS RESULT BY 10. MOV R1,-(SP) ; ASL R1 ; ASL R1 ; ADD (SP)+,R1 ; ADD R2,R1 ; GET NEW RESULT DEC R3 ; ANY MORE DIGITS TO LOOK AT? BGT 65$ ; IF GT YES, LOOP 70$: RETURN ; .END