!Revision history: ! 001 19-Jul-88 PSR made output buffer look empty BEFORE writing so that an ! event 9 after disk full can be caught & the file closed ! 22-Jun-88 PSR Stopped upper-casing file names ! Stppped creating output files ! 27-JAN-88 PSR Changes for Springboard (CON, NUL etc) ! - added a "position fails" message to POSITON IO ! 08-Jul-87 PSR corrected setting dummy handlers on TT: SCBs ! - corrested resetting EOF on terminal input on RESET INPUT ! ! >>> OPENS <<< ! ! All kinds of OPEN for Brasil ! ! Usage of SCB fields: User1 is the 'file handle' or channel number. ! User2 is a collection of flags. ! User3 chains together TTY output SCBs ! %from IMP %include Formats, Streams, Buffers, SysSpecs, Mcode, Handcall, Depio %externalbyteintegerspec Spring %alias "3L_SPRING" %externalintegerfnspec File Size %alias "3L_IMP_FILE_SIZE"(%string(255) File) %const %integer User2 Is a TTY = 1 << 0 {isatty is true for this FD} ! ! >> Fire Error << ! %routine Fire Error(%integer Sub Event, %string(255) Message) Event_Message = Message %signal 9, Sub Event, 0 %end {#################################################} {#################################################} {### ###} {### I N P U T S I D E R O U T I N E S ###} {### ###} {#################################################} {#################################################} ! ! >> CLOSE INPUT << ! %external %routine Close Input %alias "3L___close_input"(%integer SS, Aban) %record(SCB Fm) %name S == Record(SS) %integer H = S_User1 *MOV _ R0, #0 {close command} *LDR _ R1, H {file handle} *STR _ R9, [Sp, #-4]! *SWI _ Brasil Open X *LDR _ R9, [Sp], #4 %end ! ! >> POSITION INPUT << ! %external %routine Position Input %alias "3L___position_input" - (%integer SS, Position) %record(SCB Fm) %name S == Record(SS) %integer H %label Ok H = S_User1 %if H # 0 %start *MOV _ R0, #1 {write sequential pointer} *LDR _ R1, H {file handle} *LDR _ R2, Position {absolute file position} *STR _ R9, [Sp, #-4]! *SWI _ Brasil Args *LDR _ R9, [Sp], #4 *BVC _ Ok Fire Error(3, "position fails") Ok:S_Next = S_ThisB_Base S_Limit = S_Next {force a read} S_ThisB_Size = 0 {no chars in buffer} %finish S_Position = Position S_Flags = S_Flags&(\SCB Eof Pending) %end ! ! >> RESET INPUT << ! %external %routine Reset Input %alias "3L___reset_input"(%integer SS) Position Input(SS, 0) %end {###################################################} {###################################################} {### ###} {### O U T P U T S I D E R O U T I N E S ###} {### ###} {###################################################} {###################################################} %externalroutine MSDOS Break %alias "3L___msdos_break" {R1 = addr(SCB)} {R0 = Char} %record(SCBfm)%name S %integer Char *STR _ R0, Char *STR _ R1, S %if Char = NL %start %if S_Next >= S_Limit %start Call2(S_Buffer Handler, 13, Addr(S)) %else Byte(S_Next) = 13 {CR} S_Next = S_Next+1 %finish %finish %if S_Next >= S_Limit %start Call2(S_Buffer Handler, Char, Addr(S)) %else Byte(S_Next) = Char S_Next = S_Next+1 %finish %end %external %routine Break Character %alias "3L___break_character" {NOTE - this routine can only be called to output to the terminal} {R1 = addr(SCB)} {R0 = Char} %integer Char, A, Size, S %label L1 {NOTE - there is ALWAYS room for ONE more character past the limit} *LDR _ R2, [R1] {buffer pointer, S_Next} *STRB_ R0, [R2], #1 {insert terminator} *STR _ R2, [R1] {update buffer pointer} *STR _ R1, S Flush TT Output(S) %end %routine Write Multiple(%record(SCBfm)%name S) %label OK, YY %integer H, A, Size Size = S_Next - S_ThisB_Base; %return %if Size = 0 S_Next = S_ThisB_Base {001 moved here to prevent} S_Limit = S_Next + S_ThisB_Size-1 {001 loops with DISK full} H = S_User1 A = S_ThisB_Base *LDR _ R1, H {file handle} *MOV _ R0, #2 {write command} *LDR _ R2, A {address of first byte to write} *LDR _ R3, Size {number of bytes to write} *STR _ R9, [Sp, #-4]! *SWI _ Brasil Multiple X *LDR _ R9, [Sp], #4 *BCS _ YY *CMPS _ R3, #0 {none left?} *BEQ _ OK Event_Message = "file ".SCB Name(S)." full" %signal 9, 3, 0 YY:Event_Message = "failed to write to ".SCB Name(S) %signal 9, 3, 0 OK: %end %external %routine File Output Full %alias "3L___output_full" {R1 = addr(SCB)} {R0 = Char} %record(SCB Fm) %name S %integer Char, H, A, Size *STR _ R0, Char *STR _ R1, S Write Multiple(S) *LDR _ R0, Char *LDR _ R2, S *LDR _ R3, [R2] {buffer pointer} *STRB_ R0, [R3], #1 *STR _ R3, [R2] %end ! ! >> RESET OUTPUT << ! %external %routine Reset Output %alias "3L___reset_output"(%integer SS) %record(SCB Fm) %name S == Record(SS) %integer H %label Ok H = S_User1 *MOV _ R0, #1 {write sequential pointer} *LDR _ R1, H {file handle} *MOV _ R2, #0 {absolute file position} *STR _ R9, [Sp, #-4]! *SWI _ Brasil Args *LDR _ R9, [Sp], #4 *BVC _ Ok Fire Error(3, "reset output") Ok:S_Next = S_ThisB_Base %end ! ! >> CLOSE OUTPUT << ! %external %routine Close File Output %alias "3L___close_file" - (%integer SS, Abandon) %record(SCB Fm) %name S == Record(SS) %integer H, A, Size H = S_User1 Write Multiple(S) *MOV _ R0, #0 {close command} *LDR _ R1, H {file handle} *STR _ R9, [Sp, #-4]! *SWI _ Brasil Open X *LDR _ R9, [Sp], #4 %end %external %record(SCBfm)%map Open SCB %alias "3L___open_scb" - (%string(255) Pure File, %integer RW, Fd, Size) !RW&1 =0 READ, =1 WRITE !RW&2 =0 TEXT, =2 BINARY %integer Sa, Mode, J %record(SCB Fm) %name S %string(255) File %label Bug Ok {first convert to upper case & strip spaces} File = "" %for J = 1, 1, Length(Pure File) %cycle Sa = Charno(Pure File, J) %if Sa # ' ' %start Sa = Sa-32 %if 'a' <= Sa <= 'z' File = File.Tostring(Sa) %finish %repeat %if Fd < 0 %start {not given explicitly} %if File = "" %or - (Spring=0 %and File = "TT:") %or - (Spring#0 %and File = "CON") %start Fd = 0 %else File = Pure File.Tostring(13) Sa = Addr(File)+1 %if RW&1 = 0 %start {open for read only} Mode = 16_40 %else {open for write} ! {BUG in ADFS - create it big enough!!!} ! %unless Spring # 0 %or File Size(File) >= 16_40000 - ! %or Charno(File, Length(File)) = ':' %start ! *MOV _ R0, #7 {create empty file} ! *LDR _ R1, Sa ! *MOV _ R4, #0 ! *MOV _ R5, #16_40000 ! *SWI _ Brasil File X ! *BVC _ Bug Ok ! Fire Error(3, "cannot create ". FileName) ! %finish ! {end of BUG} Bug Ok: Mode = 16_80 Size = Size+1 {a hole for newline} %finish *LDR _ R0, Mode {16_40 = Input, 16_80 = Output, 16_C0 = update} *LDR _ R1, Sa {address of string} *STR _ R9, [Sp, #-4]! *SWI _ Brasil Open X *LDR _ R9, [Sp], #4 *MVNVS _ R0, #0 {result = -1 on error} *STR _ R0, Fd %if Fd <= 0 %start {an error has occured} %if Mode = 16_40 %then Pure File = Pure File." for input" - %else Pure File = Pure File." for output" Fire Error(3, "cannot open ".Pure File) %finish %finish %finish S == New SCB(Size) {one extra for BREAK} S_User1 = Fd {the file handle} Set Object Name(S, Pure File) %if RW&1 = 0 %start {open for input} S_Limit = S_Next {nothing in it for now} S_ThisB_Size = 0 {buffer empty currently} %if FD = 0 %start {terminal input} S_User2 = S_User2 ! User2 Is a TTY S_Close Handler = Addr 2(Dummy 2) S_Reset Handler = Addr 1(Reset Input) S_Position Handler = Addr 2(Dummy 2) S_Buffer Handler = Addr 0(TT Input Empty) %else {file input} S_Close Handler = Addr 2(Close Input) S_Reset Handler = Addr 1(Reset Input) S_Position Handler = Addr 2(Position Input) %if RW&2 = 0 %start {text input} S_Buffer Handler = Addr 0(Input Empty) %else {binary input} S_Buffer Handler = Addr 0(Binary Input Empty) %finish %finish %else {open for output} S_Limit = S_ThisB_Base + S_ThisB_Size-1 {onto final character} %if FD = 0 %start {terminal output} S_User2 = S_User2 ! User2 Is a TTY S_Buffer Handler = Addr 0(TT Output Full) S_Reset Handler = Addr 1(Reset Output) S_Close Handler = Addr 2(Close TT Output) S_Complete Handler = Addr 1(Flush TT Output) S_Breaks = NL+1 {break on NL} S_Break Handler = Addr 0(Break Character) Add TTY(S) %else {file output} S_Buffer Handler = Addr 0(File Output Full) S_Break Handler = S_Buffer Handler {for Pascal IO} S_Complete Handler = S_Buffer Handler S_Reset Handler = Addr 1(Reset Output) S_Close Handler = Addr 2(Close File Output) %if RW&2 = 0 %and Spring # 0 %start {text output} S_Breaks = NL+1 S_Break Handler = Addr 0(MSDOS Break) %else %if Charno(File, Length(Pure File)) = ':' {break on NL} S_Breaks = NL+1 %finish %finish %finish %result == S %end