Sequential Character File Manager
Sequential Character file manager handles interaction with terminals, printers, modems etc.
nam SCF
ttl Sequential Character file manager
* This is a LEVEL 2 module
* Originally from Dragon 128
* Copyright 1982 by Microware Systems Corporation
* Reproduced Under License
* This source code is the proprietary confidential property of
* Microware Systems Corporation, and is provided to licensee
* solely for documentation and educational purposes. Reproduction,
* publication, or distribution in any form to any party other than
* the licensee is strictly prohibited!
use defsfile
***************
* Edition History
* # date Comments by
* -- -------- --------------------------------------------- ---
* 1 82/07/11 Code inserted to initialize V.XON, V.XOFF RFD
* 1 82/10/12 Bug in ctl-A fixed; (O,S --) 2,S) RFD
* 2 83/03/16 Now uses one 256-byte buffer instead of two. RFD
* 2 83/03/16 Made PutStat allocate device(s). RFD
* 2 83/03/17 Removed high-order bit stripping. RFD
* 2 83/03/17 Line Feeds no longer print as CR LF. RFD
* 2 83/03/17 Sends SS.Relea to driver when process dies. RFD
* 3 83/11/01 Extended editing facilities and SS.Edit
* Getstt call added. Vivaway Ltd. PSD
* 83/11/10 Macros added. Vivaway Ltd. PSD
Edition equ 3 current edition number
ttl Module Header
page
***************
* Sequential Character File Manager
* Designed for terminal/printer console-type devices.
* Supports line oriented buffered input, with line
* editing (backspace, delete, repeat line, reprint
* line, echo on/off, etc.)
mod SCFEnd,SCFName,FLMGR+OBJCT,REENT+1,SCF,0
SCFName fcs "SCF"
fcb Edition Current Edition
SCF lbra SCCrea create
lbra SCOpen Open
lbra SCOErr makdir
lbra SCOErr chgdir
lbra Open90 delete
lbra Open90 seek
lbra SCRead read
lbra SCWrite write
lbra SCRdLine read line
lbra SCWrLine write line
lbra SCGStat get status
lbra SCPstat set status
lbra SCClose close
EXTEND equ 1 include extended editing facilities
MACROS equ 1 include macros
BuffSize equ $100 path buffer size
OutBfSiz equ 32 maximum size of output "buffer"
ifne MACROS
MacBfSiz equ $100 macro buffer size
endc
ttl Open/Close/GetStat etc.
page
***************
* SCCrea & SCOpen
* Process Create/Open Request
* Passed: (Y) = Path Descriptor ptr
SCCrea equ *
SCOpen ldx PD.DEV,y copy Device Table Ptr
stx PD.TBL,y for user GetSts availability
ldu PD.RGS,y get caller's register stack
pshs y save PD ptr
ldx R$X,u get pathname ptr
os9 F$PrsNam parse device name
lbcs SCOER1 ..error; bad name
tsta High order bit set?
bmi Open0 ..Yes; end of name
leax 0,y
os9 F$PrsNam check for more name
bcc SCOER1 ..error if so
Open0 sty R$X,u save updated name ptr
puls y retrieve PD ptr
ifne MACROS
ldd #BuffSize+MacBfSiz get buffer size
else
ldd #BuffSize
endc
os9 F$SRqMem allocate buffers
bcs OPNER9 ..error; return it
stu PD.BUF,y save buffer ptr
ifne MACROS
clr BuffSize,u show macro buffer empty
clr BuffSize+3,u show no macros installed
endc
clrb
***************
* This code may be optimized by "lda #C$CR"
* In severe cases when memory is expensive
bsr JAMMER
* "by K.Kaplan, L.Crane, R.Doggett"
fcb $62,$1B,$59
fcb $6B,$65,$65,$2A,$11,$1C,$0D,$0F
fcb $42,$0C
fcb $6C,$62,$6D,$31,$13,$0F,$0B
fcb $49,$0C
fcb $72,$7C,$6A,$2B,$08,$00,$02,$11,$00
fcb $79
JAMMER puls x
clra
JAMM10 eora ,x+
sta ,u+
decb
cmpa #C$CR
bne JAMM10
* end of optimizable code
***************
Open1 sta ,u+ clear out buffer
decb
bne Open1
ldu PD.DEV,y
beq SCOErr ..exit if no physical device
ldx V$STAT,u
lda PD.PAG,y reset lines-left count
sta V.LINE,x
ldx V$DESC,u now open echo/pause path
ldd PD.D2P,y
beq Open90
leax d,x get offset of secondary pathname
lda PD.MOD,y
lsra reverse read & write modes
rorb
lsra
rolb
rola
rorb
rola
pshs y save Path ptr
ldy D.Proc
ldu D.SysPrc
stu D.Proc temp switch to System process
os9 I$Attach attach auxilary device
sty D.Proc switch back to User process
puls y restore Path ptr
bcs OPNER9 ..exit if error
stu PD.DV2,y save echo/pause device
Open90 clra return carry clear
rts
SCOER1 puls pc,y error; return it
SCOErr comb return carry set
ldb #E$BPNam error - bad path name
OPNER9 rts
SCClose pshs cc save interrupt masks
orcc #IntMasks set interrupt masks
ldx PD.DEV,y get device table ptr
bsr DenyDev disassociate device signals
ldx PD.DV2,y get attached device
bsr DenyDev disassociate it too
puls cc retrieve interrupt masks
tst PD.CNT,y Last Image?
bne Close.C ..No; exit
ldu PD.DV2,y get echo/pause device
beq Close.B branch if none
os9 I$Detach detach echo/pause device
Close.B ldu PD.BUF,y get buffer address
beq Close.C ..no buffer to return
ifne MACROS
ldd #BuffSize+MacBfSiz get buffer size
else
ldd #BuffSize
endc
os9 F$SRtMem return buffers to system store
Close.C clra
rts
***************
* Subroutine DenyDev
* Eliminate ownership of device for this Process
* Passed: (X)=device tbl ptr of entry to deny
DenyDev leax 0,x device in use?
beq Close.C ..No; exit
ldx V$STAT,x get static storage ptr
ldb PD.PD,y get this path number
lda PD.CPR,y current Process ID
pshs y,x,b,a
cmpa V.LPRC,x is this last process?
bne Deny.Z exit if not
ldx D.Proc process ptr
leax P$Path,x ptr to path table
clra start with path #0
Deny.A cmpb a,x will this path still be open?
beq Deny.Z ..Yes; retain control
inca
cmpa #NumPaths all paths checked?
bcs Deny.A ..no; repeat
pshs y save PD ptr
ldd #SS.Relea*256+D$PSTA
lbsr SCGST1 send Release putstat to driver
puls y
ldx D.Proc
lda P$PID,x parent's ID
sta 0,s Try to stick parent with device
os9 F$GProcP (Y)=parent's Process ptr
leax P$Path,y parent's path tbl
ldb 1,s restore path number
clra
Deny.B cmpb a,x Parent still own path?
beq Deny.C Yes; return control to parent
inca
cmpa #NumPaths
bcs Deny.B repeat until all paths checked
clr 0,s Nobody responsible for abort signals
Deny.C lda 0,s responsible party
ldx 2,s Static storage ptr
sta V.LPRC,x
Deny.Z puls pc,y,x,b,a
***************
ifne MACROS
********************
* Install a macro
*
SCInMac lda R$Y,u get keycode
beq SCInMac6 ..none; no action
bsr SCClrM clear the macro if it exists
ldb R$Y+1,u get length
beq SCInMac6 ..none; exit
ldx PD.BUF,y get a buffer ptr
leax BuffSize+MacBfSiz,x point at end of macro buffer
pshs x save it
leax -MacBfSiz+3,x point at macro buffer
SCInMac1 lda ,x+ get code
beq SCInMac2 skip if empty
ldb ,x+ get byte count
abx skip this entry
cmpx ,s any more room?
bcc SCInMac3 ..no; error - no room
bra SCInMac1 ..try next
SCInMac2 ldb R$Y+1,u get byte count
pshs x save ptr
abx add in byte count
leax 1,x plus room for byte count
cmpx 2,s enough room?
bhi SCInMac4 ..no
beq SCInMac5 exactly fills it
clr ,x clear next entry
SCInMac5 puls x retrieve ptr
stb ,x+ set byte count
clra
pshs y,b,a stack byte count and PD ptr
lda R$Y,u get key code
sta -2,x set it
ldy D.Proc get process ptr
lda P$Task,y get source task
ldb D.SysTsk get destination task (system)
ldu R$X,u get source ptr
exg x,u swap ptrs
puls y get byte count
os9 F$Move copy the macro
puls y retrieve PD Ptr
leas 2,s return scratch
SCInMac6 clrb no error
rts
SCInMac4 leas 2,s ditch scratch
SCInMac3 leas 2,s ditch scratch
comb error -
ldb #E$MemFul no room
rts
********************
* Clear a macro
*
SCClrM ldx PD.BUF,y get buffer ptr
leax BuffSize,x point at macro buffer
lda R$Y,u get key to delete
beq SCClrM3 ..clear all
leax MacBfSiz,x calculate buffer end
pshs x save it
leax -MacBfSiz+3,x back to buffer
SCClrM1 cmpa ,x this one?
beq SCClrM2 ..yes
tst ,x+ end of buffer?
beq SCClrM4 ..yes; not found
ldb ,x+ get entry size
abx skip this entry
cmpx ,s end of buffer?
bcs SCClrM1 ..no; try again
bra SCClrM4 ..not found
SCClrM2 ldb 1,x get byte count
pshs y save PD ptr
tfr x,y copy ptr
abx point to next entry
leax 2,x code and count
SCClrM7 cmpx 2,s end of buffer?
bcc SCClrM5 ..yes; no copy needed
tst ,x entry to copy?
beq SCClrM5 ..no
lda ,x+ copy code
sta ,y+
ldb ,x+ get byte count
stb ,y+ copy it
SCClrM6 lda ,x+ copy the data
sta ,y+
decb
bne SCClrM6
bra SCClrM7 copy next
SCClrM5 clr ,y delete last entry
puls y retrieve PD ptr
SCClrM4 leas 2,s ditch scratch
clrb no error
rts
SCClrM3 clr 3,x delete first entry (and so all)
rts
********************
* Find a macro
*
SCFMac ldx PD.BUF,y get buffer ptr
leax BuffSize+MacBfSiz,x point past macro buffer
pshs x save end pointer
leax -MacBfSiz+3,x point at buffer
SCFMac1 tst ,x+ end of entries?
beq SCFMac3 ..yes; not found
ldb ,x+ get byte count
cmpa -2,x this one?
beq SCFMac2 ..yes; found it
abx skip this entry
cmpx ,s end of buffer?
bcs SCFMac1 ..no; try next
SCFMac3 comb error - not found
SCFMac2 leas 2,s ditch scratch
rts
endc
SCGStat ldx PD.RGS,y
lda R$B,x get status code
ifne EXTEND
cmpa #SS.Edit edit line?
beq SCEdit ..yes; do it
endc
cmpa #SS.OPT copy options stat?
beq SCRETN ..yes; return OK
ldb #D$GSTA
SCGST1 pshs A save function code
clra extend entry offset to two bytes
ldx PD.DEV,y dev tbl ptr
ldu V$STAT,x static storage for driver
ldx V$DRIV,x
addd M$Exec,x driver's lbra table
leax D,X
puls a restore status function code
jmp 0,x into the hands of a friendly driver
SCPstat lbsr SCALOC allocate device(s)
bsr PutStat
pshs b,cc save error status
lbsr IODONE
puls pc,b,cc
PutStat lda R$B,u get status code
ifne MACROS
cmpa #SS.SMac set macro?
lbeq SCInMac ..yes
cmpa #SS.CMac clear macro?
lbeq SCClrM ..yes
endc
ldb #D$PSTA
cmpa #SS.Opt set options?
bne SCGST1 ..No; pass status call to driver
pshs y save PD ptr
ldx D.Proc get process ptr
lda P$Task,x get process task
ldb D.SysTsk get system task
ldx R$X,u get user's option bytes
leau PD.OPT,y get options ptr
ldy #OptCnt get byte count
os9 F$Move copy options
puls y retrieve PD ptr
SCRETN rts
ttl Input Routines
page
ifne EXTEND
***************
* Scedit
* Process Edit Line Request
*
* Passed: (Y)=File Descriptor Static Storage
* User regs: (X)=Pointer to buffer
* (Y)=Max byte count
* (U)=Start cursor position
SCEdit lbsr SCALOC Allocate device(s)
bcs SCRETN exit if not allocated
ldx R$Y,u get byte count
lbeq SCRead3 ..zero; return (gained ownership)
tst R$Y,u byte count > 255?
beq SCEdit10 ..no
ldx #256 max 256
SCEdit10 pshs y,x
ldx D.Proc
lda P$Task,x
ldb D.SysTsk
ldx R$X,u
ldu PD.BUF,y
ldy ,s
os9 F$Move
puls y,x
tfr u,d
leax d,x
pshs x
lbsr SCRPET
ldu PD.RGS,y
lda R$U+1,u
pshs b
cmpa ,s+
bcs SCEdit12
tfr b,a
SCEdit12 pshs a
subb ,s+
pshs b
tfr a,b
clra
addd PD.BUF,y
tfr d,u
ldb ,s+
beq SCEDIT15
bsr SCEdit20
SCEDIT15 lbra SCRd20
SCEdit20 pshs b
lbra SCDLL2
endc
***************
* SCRead
* Process Read Request
*
* Passed: (Y)=File Descriptor Static Storage
SCRead lbsr SCALOC allocate devices
bcs SCRETN
inc PD.RAW,y
ldx R$Y,u
lbeq SCRead4
pshs x
ifne EXTEND
ldu PD.BUF,y reset buffer ptr
ldx #0 and byte count
else
jmp NOWHERE
endc
ifne MACROS
pshs x,a save regs
ldx BuffSize+1,u get possible current macro ptr
ldb BuffSize,u is there some?
bne SCRead5 ..yes; send it
puls x,a retrieve regs
endc
lbsr GetChr get character
bcs SCERR
tsta null byte?
beq SCRead2
cmpa PD.EOF,y
bne SCRead15
SCEOFX ldb #E$EOF
SCERR leas 2,s
pshs b
bsr SCRead3
comb
puls pc,b
SCRead1 tfr x,d
tstb
bne SCRead12
lbsr RetData
ldu PD.BUF,y
SCRead12 lbsr GetChr
bcs SCERR
ifne MACROS
SCRead15 pshs x,a
pshs y
lbsr SCGetDev
bcs SCRead8
cmpa PD.LdIn-PD.OPT,y
bne SCRead8
ldy ,s
lbsr GetChr
ora #$80
bcc SCRead8
leas 5,s
bra SCERR
SCRead8 puls y
sta ,s
lbsr SCFMac
bcc SCRead5
puls x,a
tst PD.EKO,y echo on?
else
SCRead15 pshs x,a
tst PD.EKO,y echo on?
endc
beq SCRead2
lbsr PutDv2 Print character
SCRead2 leax 1,x
sta ,u+
beq SCRead22
cmpa PD.EOR,y
beq SCRead25
SCRead22 cmpx ,s
bcs SCRead1
SCRead25 leas 2,s
SCRead3 lbsr RetData
ldu PD.RGS,y
stx R$Y,u
SCRead4 lbra IODONE
ifne MACROS
SCRead5 leas 1,s
pshs x,b
SCRead6 ldx 1,s
lda ,x+
sta ,u+
stx 1,s
dec ,s
tst PD.EKO,y
beq SCRead62
lbsr PutDv2 Print character
SCRead62 ldx 3,s
leax 1,x
stx 3,s
cmpx 5,s
bcc SCRead7
tfr x,d
tstb
bne SCRead65
lbsr RetData
ldu PD.BUF,y
SCRead65 tst ,s
bne SCRead6
leas 5,s
lbra SCRead12
SCRead7 ldx PD.BUF,y
puls b
stb BuffSize,x
puls b,a
std BuffSize+1,x
puls x
bra SCRead25
endc
page
***************
* SCRdLine
* Buffer a line from the Input device
* using line-editing functions
* Passed: (Y)=File Descriptor address
* (U)=Caller's register stack
SCRdLine lbsr SCALOC Allocate device(s)
ifne EXTEND
lbcs SCRETN ..exit if not allocated
else
endc
SCRd05 ldx R$Y,u Get byte count
beq SCRead3 ..zero; return (gained ownership)
tst R$Y,u Byte count above 255?
beq SCRd10 ..no
ldx #256 Maximum of 256 permitted
ifne EXTEND
SCRd10 tfr x,d
addd PD.BUF,y
pshs b,a
else
endc
lbsr SCDEL9
ifne MACROS
clr BuffSize,u cancel any current macro
endc
SCRd20 lbsr GetChr Input one char
lbcs SCABT ..i/o tremors, abort
* anda #$7F was used to strip high bit
tsta null?
beq SCRd30 Ignore control char checking if null
ldb #PD.BSP
SCRd25 cmpa b,y control character?
beq SCCTLC ..yes; dispatch to routine
incb
cmpb #PD.QUT more to check?
bls SCRd25 ..yes; repeat
ifne EXTEND
pshs y save path descriptor ptr
bsr SCGetDev get device descriptor options ptr
bcs SCRd27 skip if editing functions not available
cmpa PD.LdIn-PD.OPT,Y lead-in code?
bne SCRd60 ..no
pshs y save options ptr
ldy 2,s retrieve PD ptr
lbsr GetChr get next chr
puls y restore options ptr
bcs SCRd90 ..error
ora #$80 set bit 7 for matching
SCRd60 ldb #PD.QUT+1 point to next dispatch table
leay PD.Left-PD.OPT,y point at edit key-codes
SCRd65 cmpa ,y+ this key?
beq SCRd70 ..yes
incb
cmpb #PD.QUT+PD.DEol-PD.Left+1 more?
bls SCRd65 ..yes
* anda #$7F used to clear bit 7 and fall through
SCRd27 puls y retrieve PD ptr
else
endc
ifne MACROS
lbra SCChkMac check for macros
endc
ifne MACROS+EXTEND
SCRd30
endc
SCRd35 leax 1,x
cmpx 0,s
ifne EXTEND
leax -1,x
endc
blo SCRd40
SCRd37 lda PD.OVF,y
lbsr OUTCHR
ifeq EXTEND
endc
bra SCRd20
SCRd40 lbsr UPCASE
ifne EXTEND
lbsr SCINS
else
endc
SCRd50 bra SCRd20 Go get more
ifne EXTEND
SCRd90 puls y
lbra SCABT
SCRd70 puls y retrieve path descriptor ptr, fall through
endc
SCCTLC pshs pc,x save regs
leax CTLTBL,pcr get dispatch table
subb #PD.BSP
ifne EXTEND
pshs a save chr
lslb two bytes per entry
ldd b,x get routine offset
leax d,x make routine address
puls a retrieve chr
else
endc
stx 2,s address of table dispatch
puls x
jsr [,s++] call routine
ifne EXTEND
lbra SCRd20 back to main loop
else
endc
ifne EXTEND
page
* Process "Edit" character
SCGetDev pshs a save A
lda PD.Edit,y
pshs a
ldy PD.DEV,y
ldy V$DESC,y
leay M$DTyp,y
coma
lda ,s+ editing functions available?
bne SCGetD1 ..no
clra clear carry
SCGetD1 puls pc,a
endc
**********
* Path control char Dispatch Table
CTLTBL
ifne EXTEND
fdb SCBSP-CTLTBL Pd.bsp
fdb SCDEL-CTLTBL Pd.del
fdb SCEOL-CTLTBL Pd.eor
fdb SCEOF-CTLTBL Pd.eof
fdb SCPRNT-CTLTBL Pd.rpr
fdb SCRPET-CTLTBL Pd.dup
fdb SCDEL4-CTLTBL Pd.psc (ignore)
fdb SCDEL-CTLTBL Pd.int
fdb SCDEL-CTLTBL Pd.qut
fdb SCLFT-CTLTBL Pd.left
fdb SCRT-CTLTBL Pd.right
fdb SCDLRT-CTLTBL Pd.delch
fdb SCDELR-CTLTBL Pd.deol
else
endc
SCEOL leas 2,s discard return addr
ifne EXTEND
bsr SCMKEL Mark end of line with CR
else
endc
lbsr CHKEKO Echo character
ldu PD.RGS,y
ifne EXTEND
bsr SCGetLen calculate number of chrs
endc
leax 1,x count CR
stx R$Y,u
lbsr RetData return line
leas 2,s ditch max count
lbra IODONE
ifne EXTEND
SCGetLen exg x,d calculate line length
subd PD.BUF,y
exg d,x
rts
SCMKEL lda #C$CR
sta ,x
rts
SCChkEol pshs x
cmpu ,s
puls pc,x
endc
SCEOF leas 2,s
ifne EXTEND
cmpx PD.BUF,y
lbne SCRd30
ldx #0
lbra SCEOFX
else
endc
SCABT pshs b
ifne EXTEND
bsr SCMKEL
else
endc
ifne EXTEND
lbsr EKOCR
else
endc
puls b
lbra SCERR
ifne EXTEND
* Delete line left
SCDEL tfr u,d
subd PD.BUF,y
beq SCDEL4
pshs b
pshs b
pshs b
pshs y
ldy PD.BUF,y
bsr SCChkEol
bcc SCDEL5
SCDEL1 lda ,u+
sta ,y+
inc $04,s
bsr SCChkEol
bcs SCDEL1
SCDEL5 leax ,y
puls y
ldu PD.BUF,y
tst PD.DLO,y
beq SCDEL2
leas $03,s
lbra EKOCR
SCDEL4 rts
SCDEL2 bsr SCMLFT
dec ,s
bne SCDEL2
lbsr SCShLn
SCDEL3 bsr SCSPACE
dec 1,s
bne SCDEL3
leas $02,s
lbra SCDLL2
* Delete line right
SCDELR clr ,-s clear counter
pshs u,x save cursor and EOL ptr
leax ,u new EOL ptr
SCDELR1 cmpu ,s check end of line
beq SCDELR2 ..yes
leau 1,u bump cursor
bsr SCSPACE clear a space
inc 4,s keep count
bra SCDELR1
SCDELR2 puls u,b,a retrieve cursor and scratch
tst ,s any backspaces needed?
lbne SCDLL2 ..yes
puls pc,b
SCSPACE lda #C$SPAC write a space
lbra CHKEKO
SCMLFT pshs y save path descriptor ptr
lbsr SCGetDev point into device descriptor
bcs SCMLFT20
ldb #PD.Mlft-PD.OPT
bra SCOutX10 send it
SCMLFT20 puls y retrieve PD ptr
lbra SCBSP2 use backspace echo chr
SCMRT pshs y save path descriptor ptr.
ldb #PD.MRt-PD.OPT offset to 'move right' code
SCOutX lbsr SCGetDev point into device descriptor
bcs SCMRT30
SCOutX10 pshs x
leax ,y point at codes with X
ldy 2,s retrieve PD ptr
lda b,x get code
bpl SCMRT20
anda #$7F clear high bit
pshs a save code
lda PD.LdOut-PD.OPT,X get lead-in chr
beq SCMRT10 skip if none
bsr OUTCHR Print lead-out character
SCMRT10 puls a
SCMRT20 bsr OUTCHR Print character
SCMRT30 puls pc,y,x
SCRT bsr SCChkE at end of line?
bcc SCRT20
bsr SCMRT
bcs SCRT10
leau 1,u bump the cursor
SCRT10 rts
SCRT20 tfr u,d calculate chrs to move back..
subd PD.BUF,y
beq SCRT10
pshs b
ldu PD.BUF,y
bra SCDLL2 move to start of line
SCLFT cmpu PD.BUF,y at start of line?
beq SCLFT20 ..yes; move to end of line
bsr SCMLFT move back one
bcs SCLFT10 skip if couldn't
leau -1,u update cursor
SCLFT10 rts
SCLFT20 bsr SCChkE at end of line?
beq SCLFT30 ..yes; finished
leau 1,u bump cursor
bsr SCMRT move right one
bcc SCLFT20 repeat if OK
SCLFT30 rts
else
endc
ifne EXTEND
SCDEL9 ldx PD.BUF,y reset EOL ptr
tfr x,u and cursor
else
endc
rts
ifne EXTEND
SCBSP cmpu PD.BUF,y at start
beq SCLFT30 ..yes; return
bsr SCChkE at end of line?
bne SCDLLF ..no; delete left
else
endc
leau -1,u
leax -1,x
tst PD.BSO,y
beq SCBSP2
bsr SCBSP2
ifne EXTEND
lbsr SCSPACE send space
else
endc
SCBSP2 lda PD.BSE,y Get backspace echo char
ifne EXTEND
OUTCHR lbra EKOBYT Print character
else
endc
ifne EXTEND
SCChkE lbra SCChkEol
* Delete left one
SCDLLF lbsr SCMLFT
leau -1,u
SCDL pshs u
SCDLL1 lda 1,u
sta ,u+
bsr SCChkE
bcs SCDLL1
puls u
leax -1,x
bsr SCShLn
SCDL1 incb
pshs b
lbsr SCSPACE
SCDLL2 lbsr SCMLFT
dec ,s
bne SCDLL2
puls pc,a
* Delete character under cursor
SCDLRT bsr SCChkE at end of line?
bcc SCDLR1
leax -1,x
clrb
bsr SCChkE
bcc SCDL1
leax 1,x
bra SCDL
SCDLR1 rts
* Display to end of line
SCShLn clrb clear byte count
pshs u,b save count and U
SCShL1 bsr SCChkE end of line?
bcc SCShL2 ..yes
lda ,u+ get a chr
cmpa #C$CR done?
beq SCShL2 ..yes
lbsr CHKEKO display the chr
inc ,s keep count
bra SCShL1
SCShL2 puls pc,u,b return with forward count
* Insert a character into the buffer
SCINS bsr SCChkE at end of line?
bcs SCINS1 ..no
sta ,u+ put chr in buffer
leax 1,x bump EOL ptr
lbra CHKEKO and echo the chr
SCINS1 pshs u save cursor position
leau ,x point at end of line
SCINS3 ldb ,-U move chrs right one
stb 1,u
cmpu ,s done?
bne SCINS3 ..no; loop
leas 2,s return scratch
sta ,u put chr in buffer
leax 1,x increment EOL ptr
bsr SCShLn display to end of line
leau 1,u move cursor forward one
decb one less backspace
pshs B save count
bra SCDLL2 end move back to cursor position
endc
EKOCR lda #C$CR
lbra EKOBYT
ifne EXTEND
SCPRNT lbsr SCMKEL mark end of line
else
endc
ifne EXTEND
lbsr SCDEL9 reset buffer ptr, count
else
endc
SCPRT1 lbsr EKOCHR Print one char
ifne EXTEND
SCRPET ldx 2,s get max EOL
bsr SCShLn display rest of line
clra
pshs u
addd ,s++
tfr d,x put in X
leau ,x and U, cursor ptr
rts
else
endc
ifne MACROS
* Check character against macro table
SCChkMac pshs x,a save EOL ptr and chr
lbsr SCFMac macro key?
bcc SCRd80 ..yes
puls x,a retrieve EOL ptr and chr
lbra SCRd35
SCRd80 leas 1,s ditch chr
pshs x,b save macro ptr and byte count
ldx 3,s get EOL ptr
abx add in count
cmpx 5,s room in buffer?
bcs SCRd87 ..yes
leas 3,s ditch scratch
puls x retrieve EOL ptr
lbra SCRd37 ..line overflow
SCRd87 pshs u save buffer ptr
cmpu 5,s at end of line?
bcc SCRd95 ..yes; no copy
ldu 5,s get EOL ptr
tfr u,d put in d
subd ,s calculate chrs to move
SCRd88 lda ,-u copy chrs forward
sta ,-x
decb
bne SCRd88
ldu ,s retrieve buffer ptr
ldb 2,s and byte count
SCRd95 ldx 3,s get macro ptr
SCRd100 lda ,x+ copy the macro
sta ,u+ (updates buffer ptr too)
decb
bne SCRd100
ldx 5,s get EOL ptr
ldb 2,s retrieve byte count
abx update EOL ptr
stu 3,s save new buffer ptr
ldu ,s retrieve old ptr
lbsr SCShLn display the line
subb 2,s need to move back?
beq SCRd110 ..no
bsr SCRd120 move back to cursor position
SCRd110 ldu 3,s retrieve new buffer ptr
leas 7,s ditch scratch
lbra SCRd20 and go for next chr
SCRd120 pshs b push byte count
lbra SCDLL2 move back
endc
***************
* GetChr
* get one character from Input device
* Passed: (Y)=File Descriptor address
* returns: (A)=char
* (B)=error, cc set if error
GetDv2 pshs u,y,x
ldx PD.FST,y
ldu PD.DEV,y
bra GetChr1
GetChr pshs u,y,x
ldx PD.DEV,y
ldu PD.FST,y
beq GetChr2
GetChr1 ldu $02,u
ldb PD.PAG,y
stb V.LINE,u
GetChr2 leax ,x
beq GetChr3
tfr u,d
ldu V$STAT,x
std V.DEV2,u
ldu #D$READ
lbsr IOEXEC
GetChr3 puls pc,u,y,x
***************
* UPCASE
* Convert lower-case to upper-case
* Passed: (A)=char
* (Y)=PD
* Returns: (A)=upcased
* Destroys: none
UPCASE tst PD.UPC,y uppercase only?
beq UPCAS9
cmpa #'a
bcs UPCAS9
cmpa #'z
bhi UPCAS9
suba #'a-'A convert to uppercase
UPCAS9 rts
* Check for printable character
CHKEKO tst PD.EKO,y Echo turned on?
beq UPCAS9
EKOCHR cmpa #$7F
bcc EKOCH2
cmpa #$20
bcc EKOBYT Print character
cmpa #$0D
bne EKOCH2
EKOBYT lbra PutDv2 Print character
* Non-printable character
EKOCH2 pshs a Save code
lda #'.
bsr EKOBYT Print character
puls pc,a
***************
* Subroutine RetData
* Return Data to User's address space
*
* Passed: (X)=Bytecount
* (Y)=PD ptrs
RetData pshs y,x
ldd ,s
beq RetDat30
tstb
bne RetDat10
deca
RetDat10 clrb
ldu $06,y
ldu $04,u
leau d,u
clra
ldb 1,s
bne RetDat20
inca
RetDat20 pshs b,a
lda D.SysTsk
ldx D.Proc
ldb $06,x
ldx $08,y
puls y
os9 F$Move
RetDat30 puls pc,y,x
*****************
* IODONE
IODONE ldx D.Proc
lda P$ID,x
ldx PD.DEV,y
bsr IODO10
ldx $0A,y
IODO10 beq IODO90
ldx $02,x
cmpa $04,x
bne IODO90
clr $04,x
IODO90 rts
GetDev pshs X,A save P$ID, Dev Tbl ptr
ldx V$STAT,x get ptr to device static storage
lda V.Busy,x is device busy?
beq GetDev10 ..no; return
cmpa 0,s current process owned?
beq GetDev20 ..yes; return
pshs a save device owner
bsr IODONE release devices
puls a restore device owner
os9 F$IOQu sleep until device is available
inc PD.MIN,y
ldx D.Proc
ldb P$Signal,X is it wake-up?
puls x,a
beq GetDev ..yes; try again
coma
rts return signal as error
GetDev10 lda 0,s
sta V.Busy,x mark device as owned
sta V.LPRC,x
lda PD.PSC,y
sta V.PCHR,x initialize pause char
ldd PD.INT,y
std V.INTR,x initialize Interrupt, Abort chars
ldd PD.XON,y
std V.XON,x initialize XON, XOFF chars
lda PD.PAR,y reset device type
beq GetDev20
sta V.Type,x
GetDev20 clra
puls pc,x,a
SCALOC ldx D.Proc
lda P$ID,x get current process ID
clr PD.MIN,y
ldx PD.DEV,y
bsr GetDev allocate Input device
bcs SCAL90
ldx PD.DV2,y
beq SCAL20
bsr GetDev allocate output device
bcs SCAL90
SCAL20 tst PD.MIN,y ..devices mine?
bne SCALOC ..no; try again
clr PD.RAW,y init to cooked mode
SCAL90 ldu PD.RGS,y
rts
ttl Output Routines
page
***************
* SCWrLine
* Process Write Line Request
* Passed: (Y)= Path Descriptor ptr
SCWrLine bsr SCALOC get I/O devices
bra SCWrit00 write line
***************
* SCWrite
* Write Characters to Output device
* Passed: (Y)=File Descriptor address
SCWrite bsr SCALOC get I/O devices
inc PD.RAW,y write mode (don't cook CR)
SCWrit00 ldx R$Y,u get caller's byte count
beq SCWrit99 none; return (have gained last CTL of device)
pshs x save byte count
ldx #0 clear byte count
bra SCWrit20
SCWrit10 tfr U,D copy byte count
tstb end of buffer?
bne SCWrit40 branch if not
SCWrit20 pshs y,x save registers
ldd 0,s get byte count
ldu PD.Rgs,y get registers ptr
ldx R$X,u get source ptr
leax d,x get current ptr
ldd R$Y,u get byte count
subd 0,s get bytes remaining
cmpd #OutBfSiz more than one "chunk"?
bls SCWrit30 branch if not
ldd #OutBfSiz set max byte count
SCWrit30 pshs D save byte count
ldd PD.Buf,y get buffer ptr
inca end of buffer + 1
subd 0,s minus bytes to read
tfr D,U (U)=destination ptr
lda #C$CR mark end of buffer
sta -1,u
ldy D.Proc get process ptr
lda P$Task,y get process task
ldb D.SysTsk get system task number
puls y retrieve byte count
os9 F$Move get user data
puls y,x retrieve registers
SCWrit40 lda ,u+ get next output character
tst PD.RAW,y cooked mode?
bne SCWrit50 ..no
* anda #$7F used to strip high order bit
lbsr UPCASE check for uppercase convert
cmpa #C$LF
bne SCWrit50
lda #C$CR output EOL for line feeds
tst PD.ALF,y auto line feed on?
bne SCWrit50 ..Yes
bsr PutChr output CR
bcs SCWrErr abort if write error
lda #C$LF
SCWrit50 bsr PutChr put char in output buffer
bcs SCWrErr exit if write error
leax 1,x count byte
cmpx 0,s written enough?
bcc SCWrit60 branch if so
lda -1,u get last char
beq SCWrit10 nulls can't be end of lines
cmpa PD.EOR,y end of line?
bne SCWrit10 ..no; loop
tst PD.RAW,y write line mode?
bne SCWrit10 ..no; loop
SCWrit60 leas 2,s return scratch
SCWrit70 ldu PD.RGS,y get registers ptr
stx R$Y,u return to user
SCWrit99 lbra IODONE
SCWrErr leas 2,s return scratch
pshs b,cc save error status
bsr SCWrit70 return byte count sent
puls pc,b,cc return error status
page
***************
* PutChr
* put character in output buffer
PutDv2 pshs u,x,a
ldx PD.DV2,y
beq PutChr9
tst PD.RAW,y
bne PutChr2
cmpa #$0D
bne PutChr2
bra PutChr17
PutChr pshs u,x,a
ldx PD.DEV,y
tst PD.RAW,y
bne PutChr2
cmpa #C$CR
bne PutChr2
ldu V$STAT,x
tst V.PAUS,u
bne PutChr1
tst PD.PAU,y
beq PutChr17
dec V.LINE,u
bne PutChr17
bra PutChr15
PutChr1 lbsr GetDv2
bcs PutChr15
cmpa PD.PSC,y
bne PutChr1
PutChr15 lbsr GetDv2
cmpa PD.PSC,y
beq PutChr15
PutChr17 ldu V$STAT,x
clr V.PAUS,u
lda #C$CR
bsr WrChar
**********
* tst PD.RAW,Y "cooked" mode?
* bne PutChr9 ..no; just return
**********
***************
* EOL . Process end of line functions
* Passed: (X)=Device Table ptr
* (Y)= Path Descriptor
* returns: B,CC=error code (if error)
* Destroys: A
EOL ldb PD.NUL,y
pshs b
tst PD.ALF,y Add linefeed?
beq EOL1
lda #$0A
EOL0 bsr WrChar
bcs EOL2
EOL1 lda #$00
dec ,s
bpl EOL0
clra
EOL2 leas 1,s
PutChr9 puls pc,u,x,a return
PutChr2 bsr WrChar write character
puls pc,u,x,a
WrChar ldu #D$WRIT
***************
* IOEXEC
* Execute SCF Device's Read/Write routine
* Passed: (A)=output char (write)
* (X)=Device Table entry ptr
* (Y)= Path Descriptor ptr
* (U)=offset of routine (D$ReaD, D$Write)
* returns: (A)=Input char (read)
* (B)=error code, C=set if error
* Destroys: B,CC
IOEXEC pshs u,y,x,a
ldu V$STAT,x
clr V.WAKE,u
ldx V$DRIV,x
ldd M$Exec,x
addd $05,s
leax d,x
lda ,s+
jsr 0,x
puls pc,u,y,x
emod Module CRC
SCFEnd equ *