.TITLE RSUCMD .IDENT /V7.09/ ;***************************************************************** ; ; 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 ; ; SMT851 22-JUL-83 ADDED RSX-11M V4.1 SUPPORT ; ; SMT853 26-SEP-83 ADDED THE /GN 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 .MCALL OPEN$R,CLOSE$,GET$ 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 ! AA$V41, .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 ERR10: .ASCII "RSU -- /GN switch has invalid file specification" ERR10S=.-ERR10 ERR11: .ASCII /RSU -- Open failure on group name file/ ERR11S=.-ERR11 ERR12: .ASCII /RSU -- *WARNING* Failed to allocate group name table/ ERR12S=.-ERR12 ERR13: .ASCII /RSU -- *WARNING* Failed to allocate group name entry/ ERR13S=.-ERR13 ERR14: .ASCII /RSU -- Read error on group name file/ ERR14S=.-ERR14 ERR15: .ASCII /RSU -- *WARNING* Invalid format for group name entry/ ERR15S=.-ERR15 ; ; 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$SW GN,GNMSK,MASKW,,,GNTAB ; /GN:FILESPEC 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 ; GNTAB: CSI$SV ASCII,GRPFIL,40. ; /GN:FILESPEC CSI$ND ; BEDATE: .BLKB 10. ; /BE DATE FIELD AFDATE: .BLKB 10. ; /AF DATE FIELD DADATE: .BLKB 10. ; /DA DATE FIELD GRPFIL: ; /GN FILE SPECIFICATION .REPT 40. ; .BYTE 0 ; .ENDR ; 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 391$: 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 106$ ; 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$: ; REF. LABEL ; ; PROCESS THE /GN SWITCH ; BIT #GNMSK,MASKW ; /GN SWITCH SPECIFIED? BEQ 106$ ; IF EQ NO CALL GRPNM1 ; VALIDATE /GN FILE SPECIFICATION BCS 139$ ; IF CS, ERROR CALL GRPNM2 ; OPEN THE /GN FILE BCS 1391$ ; CALL GRPNM3 ; READ THE FILE AND ESTABLISH /GN LIST BCS 1391$ ; IF CS ERROR 106$: RETURN ; RETURN TO ROOT 139$: JMP 39$ ; PRINT COMMAND AND EXIT 1391$: JMP 391$ ; JUST EXIT ;+ ; *** 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 FIT THE 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 ; ;+ ; *** GRPNM1 ; ; THIS ROUTINE IS CALLED IF THE /GN SWITCH IS PRESENT. THE FILE ; SPECIFICATION IS VALIDATED AND THE RELEVANT FDB AREAS ARE ; FILLED IN. ; ;- GRPNM1: TSTB GRPFIL ; ANY SWITCH VALUE? BEQ 100$ ; IF EQ NO, USE DEFAULTS TSTB GRPFIL+39. ; VALUE TOO LONG? BEQ 11$ ; IF EQ NO 10$: PRINT #ERR10,#ERR10S ; INVALID FILE SPECIFICATION BR 99$ ; RETURN WITH ERROR 11$: MOV #GRPFIL,R1 ; GET ADDRESS OF FILESPEC 12$: TSTB (R1)+ ; LOOK FOR NULL BYTE AT END BNE 12$ ; IF NE, LOOP DEC R1 ; REMOVE FINAL NULL FROM COUNT SUB #GRPFIL,R1 ; CALCULATE LENGTH OF SPEC. CSI$1 #CSIBLK,#GRPFIL,R1 ; CHECK SYNTAX BCS 10$ ; IF CS, ERROR CSI$2 #CSIBLK,OUTPUT ; EXAMINE A LITTLE FURTHER BCS 10$ ; IF CS, ERROR BITB #,C.STAT(R0) ; ANY OF THESE BITS SET? BNE 10$ ; IF NE YES, THIS IS AN ERROR FDOP$R #GRPFDB,,#CSIBLK+C.DSDS ; SET DATASET DESCRIPTOR ADDRESS BR 100$ ; 99$: SEC ; ERROR DETECTED RETURN ; 100$: CLC ; EXECUTION OK RETURN ; ;+ ; *** GRPNM2 ; ; THIS ROUTINE IS CALLED TO OPEN THE FILE SPECIFIED WITH THE ; /GN SWITCH. THE FDB IS ALREADY SET UP. THE GROUP NAME TABLE ; IS ALLOCATED. ; ;- GRPNM2: OPEN$R #GRPFDB ; OPEN THE FILE FOR INPUT BCC 10$ ; IF CS, GOOD PRINT #ERR11,#ERR11S ; PRINT OPEN ERROR MESSAGE CALL $FCSEP ; GIVE ERROR DETAILS SEC ; SET CARRY TO SHOW ERROR BR 20$ ; 10$: MOV #<256.*2>,R1 ; SET SIZE OF GROUP LIST TABLE CALL CORE ; ALLOCATE FROM DYNAMIC MEMORY BCC 15$ ; PRINT #ERR12,#ERR12S ; FAILED TO ALLOCATE GROUP NAME TABLE BIC #GNMSK,MASKW ; CANCEL THE /GN SWITCH CLC ; THIS IS ONLY A WARNING BR 20$ ; 15$: MOV R0,GRPADR ; SAVE ADDRESS OF GROUP NAME TABLE 20$: RETURN ; RETURN TO CALLER ;+ ; *** GRPNM3 ; ; THIS ROUTINE IS CALLED TO ALLOCATE THE GROUP NAME TABLE BY ; READING THE FILE THAT IS ALREADY OPEN. ; THE FORMAT OF EACH LINE IS AS FOLLOWS: ; ; N/NAME ; ; WHERE "N" IS AN OCTAL NUMBER IN THE RANGE 1 TO 377, AND ; "NAME" IS A TEXT STRING UP TO 14 CHARACTERS LONG. THE ; DELIMITER "/" MAY BE REPLACED BY ANY NON-NUMERIC CHARACTER, ; BUT THE SLASH FORMAT IS RECOMMENDED. ; ANY BLANK LINES OR LINES BEGINNING WITH A SEMICOLON ARE ; IGNORED. ; ;- GRPNM3: BIT #GNMSK,MASKW ; /GN SWITCH STILL IN EFFECT? BEQ 100$ ; IF EQ NO, JUST CLOSE THE FILE 10$: GET$ #GRPFDB ; READ INPUT LINE BCC 20$ ; IF CC WE GOT SOMETHING CMPB F.ERR(R0),#IE.EOF ; END OF FILE? BEQ 100$ ; IF EQ YES PRINT #ERR14,#ERR14S ; I/O ERROR ON GROUP NAME FILE CALL $FCSEP ; GIVE FCS ERROR DETAILS SEC ; BR 102$ ; 20$: MOV F.NRBD(R0),R1 ; GET LENGTH OF LINE READ BEQ 10$ ; IF EQ ZERO, IGNORE IT CMPB GRPBUF,#'; ; COMMENT LINE? BEQ 10$ ; IF EQ YES, IGNORE IT CLRB GRPBUF(R1) ; MAKE LINE ASCIZ MOV #GRPBUF,R0 ; GET ADDRESS OF BUFFER CALL $COTB ; CONVERT GROUP NUMBER TO BINARY TST R1 ; NEGATIVE OR ZERO RESULT? BGT 25$ ; IF GT NO 22$: PRINT #ERR15,#ERR15S ; PRINT ERROR MESSAGE PRINT #GRPBUF,GRPFDB+F.NRBD ; PRINT OFFENDING LINE BR 10$ ; LOOP FOR NEXT LINE 25$: CMP R1,#377 ; VALUE TOO BIG? BGT 22$ ; IF GT YES MOV R1,R5 ; SAVE VALUE IN R5 MOV R0,-(SP) ; SAVE BUFFER POINTER 26$: TSTB (R0)+ ; LOOK FOR NULL BYTE AT END OF RECORD BNE 26$ ; IF NE LOOP DEC R0 ; REMOVE NULL BYTE SUB (SP),R0 ; CALCULATE LENGTH OF NAME BGT 27$ ; IF GT GOOD TST (SP)+ ; CLEAN STACK BR 22$ ; AND SIGNAL ERROR 27$: CMP R0,#14. ; NAME TOO LONG? BLE 28$ ; IF LE NO MOV #14.,R0 ; YES, TRUNCATE IT 28$: MOV R0,-(SP) ; SAVE LENGTH ON STACK MOV R0,R1 ; COPY LENGTH TO R1 INC R1 ; ALLOW SPACE FOR NULL BYTE CALL CORE ; ALLOCATE DYNAMIC MEMORY BCC 30$ ; IF CC GOOD CMP (SP)+,(SP)+ ; CLEAN THE STACK PRINT #ERR13,#ERR13S ; PRINT ERROR MESSAGE PRINT #GRPBUF,GRPFDB+F.NRBD ; AND LINE FROM GROUP NAME FILE BR 10$ ; TRY NEXT ONE 30$: MOV (SP)+,R2 ; RETRIEVE LENGTH OF NAME MOV (SP)+,R1 ; RETRIEVE ADDRESS OF NAME ASL R5 ; CONVERT GROUP NUMBER TO INDEX ADD GRPADR,R5 ; POINT INTO GROUP NAME TABLE MOV R0,(R5) ; SAVE ADDRESS OF BLOCK IN GROUP NAME TABLE 32$: MOVB (R1)+,(R0)+ ; COPY NAME TO DYNAMIC MEMORY BLOCK DEC R2 ; DONE YET? BGT 32$ ; IF GT NO, LOOP CLRB (R0) ; MAKE NAME ASCIZ BR 10$ ; TRY NEXT ENTRY 100$: CLOSE$ #GRPFDB ; CLOSE THE GROUP NAME FILE 102$: RETURN ; RETURN TO CALLER .END