.TITLE SRTFIO ... sort file I/O module .IDENT /120582/ .ENABL LC ; ; ; Written by Ray Di marco ; 29-Apr-82. ; ; Version 290482/02 ; ; ;----------------------------------------------------------------------------- ; ; This module is used by DBSMNG CUSPs to gain access a SORTER formatted data ; file. As this type of file can be passed to the SORTER utility for sorting ; entries, CUSPs must be able to load (write) and unload (read) such a file. ; These routines allow the file to be openned for input and output simultane- ; ously (needed by SORTER CUSP); doing so requires extreme care. Normally ; the OUTPUT stream functions will be used to store data in the file and the ; INPUT stream functions to retrieve the data after the entries have been ; sorted. The module entries are ; ; SFLINT ... called to open the sort file and reset pointers ; SFLINP ... returns R1 bytes from input stream in buffer @R0 ; SFLOUT ... outputs R1 bytes to output stream frm buffer @R0 ; SFLRST ... resets both input and output streams ; SFLEND ... performs SFLRST, writes out PARBLK and closes file ; SFLPSN ... positions input stream at entry R0 ; ; The default name of the sorter data file is 'DK:SORTER.DAT'. This may be ; changed by loading a .asciz string into SFLNME. The format of a sorter data ; file is ; ; Block 0 .WORD size ; number bytes in each entry ; .WORD numb ; number of entries in file ; .BLKW 376 ; available to user for passing parameters ; Block 1 .Blkb size ; Entry #1 ; ..... ; .Blkb size ; Entry #numb ; ; File block 0 (the header) is read into the global SFLPAR buffer by SFLINT, ; and SFLPAR is written out to file block 0 by SFLEND. ; .SBTTL Modifications ; ; ; 12-May-82 Logic error in SFLRST. If buffer was empty when attemped ; to reset file got a hard error as the READ instruction did ; not include the address of the FDB; error did not appear at ; other times as the WRITE used to flush the contents of the ; buffer setup the address of the FDB. ; .SBTTL Declarations ; ; .MCALL .PUSH,.POP ; stacking .MCALL .PRINT,.EXIT ; error handling .MCALL FILSPT ; file support ; FILSPT ; set up file support ; ; .GLOBL SFLINT,SFLEND ; entries .GLOBL SFLPSN,SFLRST ; entries .GLOBL SFLINP,SFLOUT ; entries .GLOBL SFLINC,SFLOUC ; SPECIAL ENTRIES .GLOBL SFLNME,SFLPAR,SFLFDB ; data structures ; ; .MACRO FATAL MES,?A,?B .PRINT #'B STATUS .EXIT B': .ASCIZ /'MES'/<15><12><'I-'@><200> .EVEN .ENDM FATAL ; ; .PSECT CODE ; open code area ; ------ ---- .SBTTL Routine - "SFLINT" ... Initialize module ; ; This routine is called to initialize the SFL module. It opens the ; file, reads in the parameter block, and then initializes the input ; and output streams. ; SFLINT: PURGE #SFLFDB ; ensure channel free BIS #F.NERR,FDB.FL(R5) ; disable error messages NAME STRING=#SFLNME,EXTENS=#^RDAT,ERROR=1000$ LOOKUP ERROR=1000$ ; Lookup File READ BLOCK=#0,SIZE=#400,BUFFER=#SFLPAR,ERROR=1000$; Read in HDR READ BLOCK=#1,SIZE=#400,BUFFER=#SFLIBF,ERROR=1000$; Read in data MOV #1,SFLIBK ; Block 1 in memory MOV #1,SFLOBK ; Will output to block 1 MOV #1000,SFLICT ; Have 1000 bytes in memory MOV #0000,SFLOCT ; Have 0000 bytes to output RETURN ; ALL DONE ; 1000$: FATAL ; ; .SBTTL Routine - "SFLRST" ... reset input/output streams ; ; ; This routine is called to reset the SFL stream. This involves emptying ; out any data held in the output buffer and them rewinding the input and ; output streams. ; SFLRST: .PUSH R5 ; save TST SFLOCT ; any characters in output buffer? BEQ 100$ ; no -> 100$ WRITE #SFLFDB,BLOCK=SFLOBK,BUFFER=#SFLOBF,ERROR=1000$ 100$: READ #SFLFDB,BLOCK=#1,SIZE=#400,BUFFER=#SFLIBF,ERROR=1000$ ;; MOV #1,SFLIBK ; Block 1 in memory MOV #1,SFLOBK ; Will output to block 1 MOV #1000,SFLICT ; Have 1000 bytes in memory MOV #0000,SFLOCT ; Have 0000 bytes to output .POP R5 ; restore RETURN ; ALL DONE ; 1000$: FATAL ; .SBTTL Routine - "SFLEND" ... Close out SFL stream ; ; ; This routine is called when the user is finished with the ; SFL file. It empties out the contents of the output buffer ; and closes out the file. The parameter buffer is also written ; out. ; ; SFLEND: .PUSH R5 ; save TST SFLOCT ; any characters in output buffer? BEQ 100$ ; no -> 100$ WRITE #SFLFDB,BLOCK=SFLOBK,BUFFER=#SFLOBF,ERROR=1000$ 100$: WRITE #SFLFDB,BLOCK=#0,BUFFER=#SFLPAR,ERROR=1000$ PURGE #SFLFDB ; purge channel .POP R5 ; restore RETURN ; ALL DONE ; 1000$: FATAL ; .SBTTL Routine - "SFLINP" ... input R1 bytes @R0 ; ; This routine will transfer R1 characters from the input stream ; into the user buffer @R0. ; SFLINP: .PUSH ; save MOV R0,R2 ; R2 -> buffer 10$: CALL SFLINC ; get a character MOVB R0,(R2)+ ; save it SOB R1,10$ ; loop .POP ; restore RETURN ; done ; .SBTTL Routine - "SFLOUT" ... output R1 bytes @R0 ; ; This routine is called to transfer R1 characters from the user ; buffer @R0 to the output stream. ; SFLOUT: .PUSH ; save MOV R0,R2 ; R2 -> buffer 10$: MOVB (R2)+,R0 ; get characater CALL SFLOUC ; output it SOB R1,10$ ; loop .POP ; restore RETURN ; done ; ; .SBTTL Primitive - 'SFLINC' ... input one character ; ; ; This routine is called to return the next character from the input ; stream. ; SFLINC: .PUSH ; save MOV SFLICT,R4 ; R4 = number characters in buffer BNE 100$ ; have some -> skip INC SFLIBK ; point next block READ #SFLFDB,BLOCK=SFLIBK,BUFFER=#SFLIBF,ERROR=1000$ MOV #1000,R4 ; now have a full buffer 100$: MOV #SFLIBF+1000,R5 ; R5 -> end of buffer SUB R4,R5 ; R5 -> character to get MOVB (R5),R0 ; fetch character DEC R4 ; one less char in buffer MOV R4,SFLICT ; save count .POP ; restore RETURN ; done ; 1000$: FATAL ; ; .SBTTL Primitive - "SFLOUC" ... output one byte to stream ; ; ; This routine will transfer the byte passed in R0 to the ; output stream. ; SFLOUC: .PUSH ; save MOV SFLOCT,R4 ; R4 = num chrs in buf MOVB R0,SFLOBF(R4) ; save byte INC R4 ; one more character in buf CMP R4,#1000 ; buffer full? BLO 100$ ; no -> skip WRITE #SFLFDB,BLOCK=SFLOBK,BUFFER=#SFLOBF,ERROR=1000$ INC SFLOBK ; bump up block number CLR R4 ; reset char counter 100$: MOV R4,SFLOCT ; save count .POP ; restore RETURN ; EXIT ; ; 1000$: FATAL ; .SBTTL Primitive - "SFLPSN" ... Position input stream at entry R0 ; ; This routine positions the input stream so than a read operation ; will return the first character in entry R0. (Note that the ; first entry is number 1.) This routine should only be used ; when input only is being done. ; SFLPSN: .PUSH ; save CMP R0,SFLPAR+2 ; valid entry number BHI 4000$ ; no -> abort DEC R0 ; Change from base 1 to base 0 MUL SFLPAR,R0 ; R0 = byte offset DIV #1000,R0 ; R0 = block, R1 = offset MOV #1000,SFLICT ; a full buffer --> 1000 char SUB R1,SFLICT ; SFLICT = number chars left in buffer INC R0 ; Block 0 reserved for parameters MOV R0,SFLIBK ; set up input block number READ #SFLFDB,BLOCK=R0,BUFFER=#SFLIBF,ERROR=4100$ .POP ; restore RETURN ; all done ; 4000$: FATAL 4100$: FATAL ; ; .SBTTL Data structures and variables ; ; .PSECT $$$FDB ; OPEN FILES AREA ; ------ ------ ; FDB NAME=SFLFDB,CHANNEL=12.,BUFFER=SFLPAR,SIZE=400 ; SFLICT: .WORD 0 ; bytes in input buffer SFLOCT: .WORD 0 ; bytes in output buffer SFLIBK: .WORD -1 ; last block read in SFLOBK: .WORD -1 ; last block written SFLPAR: .BLKW 400 ; holds BLOCK 0 of file SFLIBF: .BLKW 400 ; inputbuffer SFLOBF: ; start of output buffer SFLNME: .ASCIZ /DK:SORTER.DAT/ ; default file name .BLKB 1000-<.-SFLNME> ; pad out buffer ; ; .END