.TITLE DOC .MCALL FINIT$,FSRSZ$,QIOW$,DIR$,CALL,RETURN .MCALL OPEN$W,OPEN$,OPEN$R,GET$,PUT$,CLOSE$ .MCALL CSI$,CSI$1,CSI$2,GMCR$,EXIT$S .MCALL GCML$,RCML$,GCMLB$ .MCALL FDBDF$,FDAT$A,FDRC$A,FDOP$A,FDBF$A .MCALL FDOP$R,NMBLK$ ;+ ; ; DOC -- PROGRAM TO ALLOW FOR THE QUICK AND EASY ; PRODUCTION OF STANDARD DOCUMENTATION. THIS ; PROGRAM TAKES CONTROL INPUT FROM A SPECIFIED ; INPUT FILE AND GENERATES RUNOFF SOURCE FILES. ; IF THE FILE TO BE USED IS NOT SPECIFIED, IT ; USES A STANDARD DEFAULT FILE. ; ; AUTHOR: W. KORENDYK ; WRITTEN: NOVEMBER 22, 1977 ; LAST MOD: JANUARY 16, 1978 ; MOD F.BORGER MAY 1 79 FOR IAS/11D ; ; VERSION: 04.00 ; ;- ; .SBTTL >I. ERROR CONTROL ; ; ERROR SUPPORT ADDRESSES ; ERRPFX:: DIR$ #ERPRI ;PRINT ERROR PREFIX RETURN ;ERROR IS ENCOUNTERED ; DIE:: CLOSE$ #OUTFDB ;TRY CLOSING OUT FILE MOV CURFDB,R1 ;ATTEMPT TO CLOSE 1$: CLOSE$ @R1 ;ALL THE INPUT FILES TST -(R1) ;POINT TO PREVIOUS CMP #FDBS,R1 ;IF THERE IS ONE, BLOS 1$ ;AND THERE IS BR TERMIN ;AND EXIT SYSTEM ; RSTART: MOV SPSAVE,SP ;RESTORE THE STACK POINTER MOV #FDBS,CURFDB ;RESET FDB QUEUE MOV #BASE,POINT ;AND THE MARK LIFO RCML$ #GCBLK ; BR START2 ;NOW START AGAIN ; TERMIN: EXIT$S ;AND STOP ON AN EOF ; SPSAVE: .WORD 0 ;SAVE SP HERE ; ;ERROR ROUTINES ; CS1ERR: CALL ERRPFX ;SET ERROR PREFIX DIR$ #NAMERR ;REPORT NAME ERROR SEC ;SHOW ERROR RETURN ; CS2ERR: CALL ERRPFX ;SET ERROR PREFIX DIR$ #DEVERR ;REPORT DEVICE ERROR SEC ;SHOW ERROR RETURN ; IOERR: CALL ERRPFX ;SET PREFIX DIR$ #FILERR ;REPORT FILE ERROR SEC ;SHOW ERROR RETURN .SBTTL >II. MAIN LINE CODE START: FINIT$ ;AND FOR FILE I/O ; START2: MOV SP,SPSAVE ;SAVE SP FOR ERROR RESTART GCML$ #GCBLK ;GET THE COMMAND LINE CMPB #GE.EOF,GCBLK+G.ERR ;END OF FILE ON COMMAND INPUT ? BNE 5$ ;NO JMP DIE ;YES, SO QUIT 5$: TSTB GCBLK+G.ERR ;ANY OTHER ERRORS ? BPL 6$ ;NO CALL ERRPFX ;REPORT COMMAND LINE FILE ERROR DIR$ #CMDERR JMP DIE ;AND QUIT ;FILL IN POINTERS IN CSI BLOCK 6$: MOV GCBLK+G.CMLD+2,CSBLK+C.CMLD+2 MOV GCBLK+G.CMLD,CSBLK+C.CMLD CSI$1 #CSBLK ;AND PARSE IT CSI$2 #CSBLK,OUTPUT ;GET OUTPUT NAME BITB #CS.NMF,C.STAT(R0) ;IS ONE GIVEN? BEQ 4$ ;NO MOV #OUDSDS,R5 ;WHERE TO PUT DSDS CALL SAVEDS ;AND PUT IT THERE ; 4$: BITB #CS.EQU,C.STAT(R0) ;IS THERE AN '='? BEQ 1$ ;IF EQ THEN NO ; CSI$2 #CSBLK,INPUT ;PARSE INPUT NAME BITB #CS.NMF,C.STAT(R0) ;IS THERE A NAME? BEQ 1$ ;IF EQ THEN NO FDOP$R @CURFDB,,#CSBLK+C.DSDS 1$: OPEN$W #OUTFDB,,,,,,IOERR ;OPEN OUTPUT FILE BCC 2$ ;BR IF OPEN WENT JMP DIE ;ELSE QUIT 2$: OPEN$R @CURFDB,,,,,,IOERR ;OPEN INPUT FILE BCC 3$ ;BR IF OK JMP DIE ;ELSE QUIT ; 3$: MOV #BUF1,R1 ;ADDRESS OF INPUT BUFFER, CALL GOTOIT ;GO TO IT ; DONE: CLOSE$ @CURFDB,IOERR ;CLOSE IN-FILE CLOSE$ #OUTFDB,IOERR ;CLOSE OUT-FILE JMP RSTART ;AND RESTART ; ;+ ; SAVEDS - ROUTINE TO SAVE THE DSDS AS PARSED INTO ; THE CSI CONTROL BLOCK. ; ; INPUTS: R5 => WHERE TO SAVE DSDS ; ;- SAVEDS: MOV R0,-(SP) MOV R1,-(SP) MOV R5,-(SP) MOV #CSBLK+C.DSDS,R0 ; ADDRESS OF DSDS MOV #6,R1 ;LOOP COUNTER 1$: MOV (R0),(R5)+ ;MOVE IT IN CLR (R0)+ ;CLEARING OUT CSBLK SOB R1,1$ MOV (SP)+,R5 MOV (SP)+,R1 MOV (SP)+,R0 RETURN ;RETURN .SBTTL >III. WRITING AND READING BLOCK ;+ ; ; GOTOIT -- ROUTINE WHICH ACTUALLY ACCOMPLISHES ; THE READING AND WRITING FROM FILE TO FILE. ; ; INPUTS: ?????? ; ; OUTPUTS: ?????? ; ;- GOTOIT: MOV R1,-(SP) MOV R2,-(SP) MOV R3,-(SP) MOV R4,-(SP) 100$: GET$ @CURFDB,R1 ;GET A RECORD BCC 10$ ;ALL IS COOL CMPB #IE.EOF,F.ERR(R0) ;AN EOF? BEQ 200$ ;WE'RE DONE CALL IOERR ;SOMETHING ELSE 10$: MOV F.NRBD(R0),R2 ;GET RECORD SIZE MOV #CONTAB,R0 ;CONTROL CHARACTER TABLE 11$: CMPB (R0)+,(R1) ;IS RECORD A CONTROL LINE? BEQ 20$ ;YES IT IS TSTB (R0) ;WAS THAT THE LAST CON. CHAR? BEQ 110$ ;YES, SO NORMAL OUTPUT BR 11$ ;NO, SO TRY THE NEXT ONE. ; 20$: SUB #CONTAB,R0 ;GET DISPLACEMENT IN TABLE DEC R0 ;IN ZERO OFFSET ASL R0 ;AS A WORD COUNT CALL @DISTAB(R0) ;DISPATCH TO ROUTINE. BR 100$ ;THAT DONE, RESUME INPUT ; 110$: CALL OUTPUT ;NORMAL OUTPUT BR 100$ ;GO FOR MORE ; 200$: MOV (SP)+,R4 MOV (SP)+,R3 MOV (SP)+,R2 MOV (SP)+,R1 RETURN ; .SBTTL >IV. CONTROL CHARACTER .SBTTL > A. RECOGNITION TABLE ; ; CONTROL CHARACTER RECOGNITION TABLE ; CONTAB: .BYTE '# ;MARK FILE POSITION .BYTE '? ;RESUME WITH TERMINAL INPUT .BYTE '@ ;INDIRECT FILE ACCESS .BYTE '" ;TEMINAL OUTPUT .BYTE 0 ;TABLE TERMINATION .EVEN .SBTTL > B. DISPATCH TABLE ; ; CONTROL CHARACTER DISPATCH TABLE ; DISTAB: .WORD MARK ;MARK FILE POSITION .WORD INTI ;RESUME WITH TERMINAL INPUT .WORD INDIR ;INDIRECT FILE ACCESS .WORD PROMPT ;TERMINAL OUTPUT .WORD 0 ;TABLE TERMINATION .SBTTL >V. CONTROL FUNCTIONS .SBTTL > A. REMEMBER FILE POSITIONS .SBTTL > 1. MARK CURRENT POSITION ;+ ; MARK -- ROUTINE TO MARK THE CURRNT POSITION, AND ; REMEMBER IT FOR LATER REFERENCE. ; ;- MARK: MOV R1,-(SP) MOV R2,-(SP) MOV R3,-(SP) MOV R5,-(SP) MOV #OUTFDB,R0 ;FILE TO MARK MOV POINT,R5 ;THE "STACK" POINTER CMP #BOT,R5 ;STILL IN "STACK" BLOS 10$ ;NO, ERROR CALL .MARK ;OBTAIN THE POSITION, BCC 5$ ;WORKED GREAT CALL IOERR ;NOT SO GREAT 5$: MOV R1,(R5)+ ;AND STACK THEM. MOV R2,(R5)+ ; MOV R3,(R5)+ ; MOV R5,POINT ;AND REMEMBER POINTER 6$: MOV (SP)+,R5 MOV (SP)+,R3 MOV (SP)+,R2 MOV (SP)+,R1 RETURN ; 10$: CALL ERRPFX DIR$ #INDERR ;REPORT END OF INDIRECTS REACHED CALL DIE BR 6$ ; .SBTTL > 2. UNMARK AND REWIND OUTPUT ; ;+ ; UNMARK -- ROUTINE TO REWIND FILE TO THE LAST MARK. ; ;- UNMARK: MOV R1,-(SP) MOV R2,-(SP) MOV R3,-(SP) MOV R5,-(SP) MOV #OUTFDB,R0 ;FILE TO REWIND MOV POINT,R5 ;GET "STACK POINTER CMP #BASE,R5 ;CHECK BOUNDS BHIS 10$ ;NO PLACE TO REWIND TO MOV -(R5),R3 MOV -(R5),R2 MOV -(R5),R1 MOV R5,POINT ;NEW POINTER CALL .POINT ;POSITION IN FILE BCC 10$ ;WORKED GREAT CMPB F.ERR(R0),#IE.EOF ;END OF FILE ? BEQ 10$ ;IF AT END OF FILE COULD BE, SO TRY ANYWAY CALL IOERR ;NOT SO GREAT BR 11$ ;AND SKIP RESETING 10$: MOV R1,OUTFDB+F.EFBK ;IN CASE THERE IS NO MORE OUTPUT, MOV R2,OUTFDB+F.EFBK+2 ;REWRITE ENDFILE BLOCK NUMBER MOV R3,OUTFDB+F.FFBY ;AND FIRST FREE BYTE POINTER 11$: MOV (SP)+,R5 MOV (SP)+,R3 MOV (SP)+,R2 MOV (SP)+,R1 RETURN ; .SBTTL > 3. REMOVE LAST MARKED POSITION ;+ ; CLEAR -- ROUTINE TO REMOVE THE LAST MARKED POSITION ; ;- CLEAR: CMP #BASE,POINT ;AT BASE? BHIS 1$ ;YEH, NOTHING TO DO SUB #6,POINT ;REMOVE MARK 1$: RETURN ; ; .SBTTL > 4. MARKING STACK ; ;+ ; STORAGE FOR FILE MARKING ; ; NOTE THAT NESTING LEVEL IS SET AT 5 ; ;- LEV =5 POINT: .WORD BASE BASE: .BLKW LEV*3 BOT: .WORD 0 .SBTTL > B. BEGIN READING FROM TERMINAL ;+ ; INTI -- ROUTINE TO READ IN FROM THE TEMINAL. ; INPUT TERMINATES AND RESORTS BACK TO ; THE CALLER ON RECEIPT OF A EOF. ; ; INPUTS: R1 = CURRENT RECORD BUFFER ADDRESS ; R2 = CURRENT RECORD BUFFER SIZE ; ; OUTPUTS: SAME ; ;- INTI: MOV R1,-(SP) MOV R2,-(SP) OPEN$R #TIFDB,,,,,,IOERR ;OPEN TERMINAL AS FILE FOR INPUT GET$ ,R1 ;READ A RECORD BCC 2$ ;WAS GOOD CMPB #IE.EOF,F.ERR(R0) ;AN EOF? BEQ 10$ ;YES CALL IOERR ;SOMETHING ELSE 1$: GET$ #TIFDB,R1 ;READ NEXT RECORD BCC 2$ ;GOT IT CMPB #IE.EOF,F.ERR(R0) ;AN EOF? BEQ 20$ ;YES CALL IOERR ;NO, SOMETHING ELSE 2$: MOV F.NRBD(R0),R2 ;GET RECORD SIZE CALL OUTPUT ;OUTPUT RECORD IN HAND BR 1$ ;AND GET MORE ; 10$: CALL UNMARK ;UNMARK THE OUTPUT BR 30$ ;AND LEAVE ; 20$: CALL CLEAR ;CLEAR THE LAST MARK 30$: CLOSE$ #TIFDB,IOERR ;CLOSE OFF TERMINAL MOV (SP)+,R2 MOV (SP)+,R1 RETURN ; .SBTTL > D. INDIRECT FILE PROCESSING .SBTTL > 1. PROCESS NEXT LEVEL ; ;+ ; ; INDIR -- ROUTINE TO OPEN THE NEXT LEVEL OF FILE ; INDIRECTION. CURRENTLY, EACH FILE IS LEFT ; OPEN AS THE NEXT LEVEL OF INDIRECTION IS ; ATTAINED. HOPEFULLY, THIS CAN BE RELIEVED ; LATER WITH THE USE OF THE MARK AND POSITION. ; ; INPUTS: R1 = ADDRESS OF LAST RECORD READ. ; ("@FILENAME") ; R2 = LENGTH OF LAST RECORD READ ; ;- INDIR: MOV R1,-(SP) MOV R2,-(SP) INC R1 ;SKIP OVER '@' DEC R2 ; CALL PRSE ;PARSE THE NAME GIVEN CALL GETFDB ;GET NEXT AVALABLE FDB BCC 1$ ;ISN'T ONE TO GET CALL 3$ ;ISSUE WARNING BR 2$ ;AND CONTINUE 1$: FDOP$R R0,,#CSBLK+C.DSDS ;INSERT DSDS OPEN$R R0,,,,,,IOERR ;OPEN THE FILE CALL GOTOIT ;GO TO IT FROM THERE CLOSE$ @CURFDB,IOERR ;DONE WITH THIS FILE CALL RELFDB ;FREE FDB 2$: MOV (SP)+,R2 MOV (SP)+,R1 RETURN ; ; ; 3$: CALL ERRPFX ;ERROR PREFIX DIR$ #INDERR ;REPORT INDIRECT ERROR RETURN .SBTTL > 2. PARSE FILE NAME ;+ ; ; PRSE -- ROUTINE TO PARSE THE GIVEN FILE NAME, AND ; LEAVE RESULTING DSDS IN CSI BLOCK. ; ; INPUTS: R1 = COMMAND LINE ; R2 = LENGTH OF COMMAND LINE ; ; OUTPUTS: R0 = ADDRESS OF CSI BLOCK ; CSI BLOCK OFFSET C.DSDS IS FILLED ; AS FOR FIRST PARSE OF OUTPUT ; SPECIFIER. ; ;- PRSE: CSI$1 #CSBLK,R1,R2 ;PARSE FILE NAME BCC 1$ ;WAS COOL CALL CS1ERR ;NOT GOOD 1$: CSI$2 ,OUTPUT ;GET A DSDS BCC 2$ ;GOT IT. CALL CS2ERR ; 2$: RETURN ; .SBTTL > 3. GET NEXT AVAILABLE FDB ; ;+ ; ; GETFDB -- ROUTINE TO PULL THE NEXT AVAILABLE ; FDB FROM THE LIST OF FDBS. ; ; OUTPUTS: CURFDB = ADDRESS OF FDB POINTER ; R0 = FDB POINTER ; CARRY SET IF NO FDB AVAILABLE ; ;- GETFDB: MOV R1,-(SP) MOV CURFDB,R1 ;GET CURRENT POINTER MOV (R1)+,R0 ;GET FDB FROM IT MOV (R1),R0 ; BEQ 1$ ;NOTHING THERE MOV R1,CURFDB ;UPDATE POINTER CLC ;INDICATE SUCCESS BR 2$ ;LEAVE 1$: SEC ;INDICATE FAILURE 2$: MOV (SP)+,R1 RETURN .SBTTL > 4. RELEASE CURRENT FDB ; ;+ ; ; RELFDB -- ROUTINE WHICH TAKES THE CURRENTLY POINTED ; TO FDB AS DEFUNCT, AND BACKS UP THE LIST TO THE ; LAST AVAILABLE FDB. ; ; OUTPUTS: CARRY SET IF THERE WAS NO LAST AVAILABLE FDB ; ;- RELFDB: MOV R1,-(SP) MOV CURFDB,R1 ;GET CURRENT CMP #FDBS,-(R1) ;UPDATE BHI 1$ ;STILL IN TABLE TST (R1)+ ;GET BACK INTO LIST SEC ;INDICATE FAILURE BR 2$ ;LEAVE 1$: MOV R1,CURFDB ;NEW POINTER CLC ;INDICATE SUCCESS 2$: MOV (SP)+,R1 ;RESTORE RETURN ; .SBTTL > E. TERMINAL OUTPUT (PROMPT) ; ;+ ; ; PROMPT -- ROUTINE WHICH OUTPUTS THE CURRENT RECORD ; AS A PROMPT TO THE TERMINAL. ; ; INPUTS: R1 = ADDRESS OF CURRENT RECORD ; R2 = SIZE OF CURRENT RECORD ; ; NOTE: THE CONTROL CHARACTER IS REMOVED FROM THE ; RECORD BEFORE OUTPUT AND REPLACED WITH ; A NULL CHARACTER ;- PROMPT: OPEN$W #TIFDB ;OPEN TI FOR WRITE MOVB #'>,(R1) ;OVERWRITE FLAG CHARACTER PUT$ #TIFDB,R1,R2 CLOSE$ #TIFDB ;LOTS OF OPENS AND CLOSES, BUT ONE LINE PROMPTS USUALLY RETURN ; ; ; .SBTTL >VI. OUTPUT A RECORD ;+ ; OUTPUT -- ROUTINE TO OUTPUT A RECORD (THE ; CURRENT RECORD) TO THE OUTPUT FILE ; ; INPUTS: R1 = BUFFER ; R2 = LENGTH ; ; ;- OUTPUT: PUT$ #OUTFDB,R1,R2,IOERR RETURN .SBTTL >VII. BUFFERS AND VARIABLES .SBTTL > A. FILE BUFFERS AND FDBS .SBTTL > 1. LUNS AND EVFS .NLIST BEX ; ; INDLEV =4 ;LEVEL OF INDIRECTION ; ; EVF'S AND LUNS ; OUTLUN =1 ;OUTPUT FILE LUN OUTEVF =1 ;AND EVF ; TILUN =2 ;TERMINAL IO LUN TIEVF =2 ;AND EVF ; TIFLUN =3 ;TERMINAL "FILE" LUN TIFEVF =3 ;AND EVF ; INFLUN =4 ;THE FIRST IN-FILE LUN INFEVF =4 ;AND EVF .SBTTL > 2. INPUT FDBS ; ; ; THE INPUT FILES ; .MACRO FDBDF,N FDB'N: FDBDF$ ;DEFINE FDB BLOCK FDAT$A R.VAR,FD.CR ;FILE ATTRIBUTES FDRC$A ,BUF1,132. ;RECORD FDOP$A INFLUN+DD,INDSDS,NMBLK1 ;FILE NAME FDBF$A INFEVF+DD ;EVF .ENDM ; DD=0 .REPT INDLEV FDBDF \DD DD=DD+1 .ENDR ; ; .MACRO FDBLST,N .WORD FDB'N .ENDM ; DD=0 FDBS=. .REPT INDLEV FDBLST \DD DD=DD+1 .ENDR .WORD 0 ;LIST TERMINATOR ; ; CURFDB: .WORD FDBS ;FIRST FDB ; INDSDS: .WORD LDEV,DEV .WORD LUIC,UIC .WORD LNAM,NAM ; DEV: .ASCII /SY0:/ ;DEFAULT DEVICE LDEV =.-DEV ; UIC: .ASCII /[1,1]/ ;DEFAULT UIC LUIC =.-UIC ; NAM: .ASCII /DOC.RNP;0/ ;DEFAULT NAME LNAM =.-NAM .EVEN ; NMBLK1: NMBLK$ DOC,RNP,,SY,0 ;HIS DEFAULTS ; (IF DSDS GETS REPLACED) .SBTTL > 3. OUTPUT FDB ; ; ; THE OUTPUT FDB ; ; OUTFDB: FDBDF$ ;DEFINE FDB BLOCK FDAT$A R.VAR,FD.CR ;FILE ATTRIBUTES FDRC$A ,BUF1,132. ;RECORD FDOP$A OUTLUN,OUDSDS,NMBLK2 ;FILE NAME FDBF$A OUTEVF ;EVF ; OUDSDS: .WORD 0,0 .WORD 0,0 .WORD 0,0 ; NMBLK2: NMBLK$ RNOPRE,RNO,,SY,0 ;DEFAULT NAME ; .SBTTL ? 4. TERMINAL FDB ;;;;; ; ; THE TERMINAL'S FDB ; TIFDB: FDBDF$ ;DEFINE FDB BLOCK FDAT$A R.VAR,FD.CR ;FILES ATTRIBUTES FDRC$A ,BUF1,80. ;RECORD FDOP$A TIFLUN,TIDSDS ;FILE NAME FDBF$A TIFEVF ;FILE EVF ; TIDSDS: .WORD LTI,TI .WORD 0,0 .WORD 0,0 ; TI: .ASCII /TI:/ LTI =.-TI .EVEN .SBTTL > B. MISCELLANEOUS .SBTTL > 1. CSI CONTROL BLOCK ; CSI$ CSBLK: .BLKB C.SIZE .EVEN ; .SBTTL > 2. TERMINAL ERROR MESSAGES AND DPB'S ; ERPRI: QIOW$ IO.WVB,TILUN,TIEVF,,,, PRIMES: .ASCII /***RNP---/ PRILEN=.-PRIMES .EVEN SYNERR: QIOW$ IO.WVB,TILUN,TIEVF,,,, SYNMES: .ASCII /SYNTAX ERROR***/ SYNLEN=.-SYNMES .EVEN INDERR: QIOW$ IO.WVB,TILUN,TIEVF,,,, INDMES: .ASCII /MAXIMUM INDIRECT FILE DEPTH***/ INDLEN=.-INDMES .EVEN NAMERR: QIOW$ IO.WVB,TILUN,TIEVF,,,, NAMMES: .ASCII /BAD FILE NAME***/ NAMLEN=.-NAMMES .EVEN DEVERR: QIOW$ IO.WVB,TILUN,TIEVF,,,, DEVMES: .ASCII /BAD DEVICE NAME***/ DEVLEN=.-DEVMES .EVEN FILERR: QIOW$ IO.WVB,TILUN,TIEVF,,,, FILMES: .ASCII /ERROR ON FILE IO***/ FILLEN=.-FILMES .EVEN CMDERR: QIOW$ IO.WVB,TILUN,TIEVF,,,, CMDMES: .ASCII /ERROR ON INDIRECT COMMAND FILE***/ CMDLEN=.-CMDMES .EVEN ; .SBTTL > 3. GCML CONTROL BLOCK ; GCLUN =TILUN GCBLK: GCMLB$ 2,RNP,,GCLUN ; .SBTTL > 4. THE REST ; ; GMCR BLOCK ; GMCR: GMCR$ ; BUF1: .BLKW 132. ;THE RECORD BUFFER ; FSRSZ$ INDLEV+4 ;MAKE ROOM FOR FILE STORAGE .END START