BSD 3 development
[unix-history] / usr / src / cmd / px / 35iosubs.s
#\f
# 35iosubs.s
#
# IO SUBROUTINES
#
.globl _getname #activate a file
.globl _unit #establish active file
.globl _iosync #syncronize a file window
.globl _unsync #push backed synced record for formatted read
.globl _pflush #flush all active files
.globl _pclose #close selected files
.globl _pmflush #flush pxp buffer
#
# system I/O routines
#
.globl _fclose
.globl _fflush
.globl _fopen
.globl _fprintf
.globl _fputc
.globl _fread
.globl _fscanf
.globl _fwrite
.globl _mktemp
.globl _rewind
.globl _sscanf
.globl _ungetc
.globl _unlink
#
# standard files
#
# file records
#
.set fnamesze,76 #maximum size of file name
.set recsze,30+fnamesze #file record size
.set FNAME,-recsze #name of associated UNIX file
.set LCOUNT,-30 #number of lines of output
.set LLIMIT,-26 #maximum number of text lines
.set FBUF,-22 #FILE pointer
.set FCHAIN,-18 #chain to next file
.set FLEV,-14 #ptr to associated file variable
.set PFNAME,-10 #ptr to name of error msg file
.set FUNIT,-6 #file status flags
.set FSIZE,-4 #size of elements in the file
.set WINDOW,0 #file window element
#
# unit flags
#
.set FDEF,0x8000 #1 => reserved file name
.set FTEXT,0x4000 #1 => text file, process EOLN
.set FWRITE,0x2000 #1 => open for writing
.set FREAD,0x1000 #1 => open for reading
.set TEMP,0x0800 #1 => temporary file
.set SYNC,0x0400 #1 => window is out of sync
.set EOLN,0x0200 #1 => at end of line
.set EOF,0x0100 #1 => at end of file
#
# bit positions of unit flags
#
.set fDEF,15
.set fTEXT,14
.set fWRITE,13
.set fREAD,12
.set fTEMP,11
.set fSYNC,10
.set fEOLN,9
.set fEOF,8
#
# standard file buffers
#
.set ioEOF,4 #bit position flagging EOF
.set ioERR,5 #bit position flagging I/O error
.set FLAG,12 #record offset of error flag
#
# standard input file
#
.data
.space fnamesze #name of associated UNIX file
.long 0 #line count
.long 0 #line limit
.long __iob #FILE pointer
.long stdout #chain to next file
.long 0 #ptr to associated file variable
.long sinnam #ptr to name of error msg file
.word FTEXT+FREAD+SYNC #file status flags
.long 1 #size of elements in the file
stdin:
.word 0 #file window element
#
# standard output file
#
.space fnamesze #name of associated UNIX file
.long 0 #line count
.long 0 #line limit
.long __iob+16 #FILE pointer
.long stderr #chain to next file
.long 0 #ptr to associated file variable
.long soutnam #ptr to name of error msg file
.word FTEXT+FWRITE+EOF #file status flags
.long 1 #size of elements in the file
stdout:
.word 0 #file window element
#
# standard error file
#
.space fnamesze #name of associated UNIX file
.long 0 #line count
.long 0 #line limit
.long __iob+32 #FILE pointer
.long 0 #chain to next file
.long 0 #ptr to associated file variable
.long msgnam #ptr to name of error msg file
.word FTEXT+FWRITE #file status flags
.long 1 #size of elements in the file
stderr:
.word 0 #file window element
tmpname:.byte 't,'m,'p,'.,'X,'X,'X,'X,'X,'X, 0
.text
sinnam: .byte 's,'t,'a,'n,'d,'a,'r,'d,' ,'i,'n,'p,'u,'t, 0
soutnam:.byte 's,'t,'a,'n,'d,'a,'r,'d,' ,'o,'u,'t,'p,'u,'t, 0
msgnam: .byte 'M,'e,'s,'s,'a,'g,'e,' ,'f,'i,'l,'e, 0
monout: .byte 'p,'m,'o,'n,'.,'o,'u,'t, 0
rdopen: .byte 'r, 0
wtopen: .byte 'w, 0
.set formfeed,12
.set linefeed,10
.set blank,'
#
# getname
#
# takes the width of a string in the subopcode and
# returns a pointer to a file structure in r0
#
# there should be a string on the stack
# of length the contents of subopcode on top of
# a pointer to the file variable
#
# a new file structure is allocated if needed
# temporary names are generated, and given
# names are blank trimmed
#
# if a new file buffer is allocated, the address
# is stored in the file variable.
#
#
_getname:
.word R6|R7|R8|R9|R11
cvtbl (r10)+, r8 # r8 has file name length
moval 4(ap), r9 # r9 will point to cleared stack
addl2 r8, r9
blbc r9,l3501
incl r9
l3501:
movl ( r9)+, r11 # r11 pts to file variable
tstl ( r11) #check for existing file record
bneq gotone
#
# allocate and initialize a new file record
#
clrl r7 # r7 has status flags
cvtwl (r10)+,r6 #r6 has data size
bneq l3502
movw $FTEXT, r7 #default to text file
movl $1,r6 #default size
l3502:
addl3 $recsze,r6,-(sp)#size of record
calls $1,_palloc #r0 points to allocated buffer
addl2 $recsze,r0 #adjust to base of record
l3503:
clrl LCOUNT(r0) #set default line limits
movl _llimit,LLIMIT(r0)
movw r7,FUNIT(r0) #set flags
movl r6,FSIZE(r0) #set size
movl r11,FLEV(r0) #set ptr to file variable
movl r0,( r11) #set file var ptr
#
# link the new record into the file chain
#
movl $_fchain-FCHAIN,r6 #r6 pts to "previous" record
movl _fchain,r1 #r1 pts to "next" record
brb l3505
l3504:
movl r1,r6 #advance previous
movl FCHAIN(r1),r1 #get next
l3505:
cmpl FLEV(r1), r11 #check level
blssu l3504 #continue until greater
movl r1,FCHAIN(r0) #link in new record
movl r0,FCHAIN(r6)
movl r0, r11 # r11 points to file record
jbr setname
#
# have a previous buffer, dispose of associated file
#
gotone:
addl2 $2,r10 #discard data size
movl ( r11), r11 # r11 points to file record
bicw2 $~(FDEF+TEMP+FTEXT),FUNIT( r11) #clear status flags
bbc $fDEF,FUNIT( r11),l3506 #check for predefined file
bicw2 $FDEF,FUNIT( r11) #clear predefined flag
jbr setname
l3506:
pushl FBUF( r11) #flush and close previous file
calls $1,_fclose
movl FBUF( r11),r0
bbs $ioERR,FLAG(r0),eclose
bbc $fTEMP,FUNIT( r11),setname #check for temp file
tstl r8 #remove renamed temp files
beql setname
pushl PFNAME( r11)
calls $1,_unlink
tstl r0 #check for remove error
beql setname
movl PFNAME( r11),_file
movw $EREMOVE,_perrno
moval error,PC(fp) #error return
ret
eclose:
movl PFNAME( r11),_file
movw $ECLOSE,_perrno
moval error,PC(fp) #error return
ret
#
# get the filename associated with the buffer
#
setname:
tstl r8 #check for a given name
bneq l3508 #br => has a name
tstb FNAME( r11) #check for no current name
bneq l3513 #br => had a previous name so use it
#
# no name given and no previous name, so generate
# a new one of the form tmp.xxxxxx
#
bisw2 $TEMP,FUNIT( r11)#set status to temporary
pushal tmpname #get a unique temp name
calls $1,_mktemp
movl $13, r8 #max length of temp name
brb l3511
#
# name is given, strip trailing blanks
#
l3508:
bicw2 $TEMP,FUNIT( r11)#set permanent status
moval 4(ap),r0 #r0 pts to end of file name
addl3 r8,r0,r1 #r1 pts to end of name
l3509:
cmpb -(r1),$blank #delete trailing blanks
bneq l3511 #(note: could use "scanc" with source
clrb (r1) # and table reversed)
sobgtr r8,l3509
#
# put the new name into the structure
#
l3511:
cmpl r8,$fnamesze #check for name too long
blss l3512
movw $ENAMESIZE,_perrno
moval error,PC(fp) #error return
ret
l3512:
movc3 r8,(r0),FNAME( r11) #move name into record
clrb FNAME( r11)[ r8] #place null char after name
moval FNAME( r11),PFNAME( r11) #set pointer to name
l3513:
movl r9,r1 #return ptr to updated stack
movl r11,r0 #return ptr to file record
ret
#
# unit establishes a new active file
#
_unit:
.word 0
movl 4(ap),r7
beql erefinaf
bbs $fDEF,FUNIT(r7),erefinaf
movl PFNAME(r7),_file
cmpl r7,$stdin #flush stdout if activating stdin
bneq l3523
cmpw _bufopt,$1 # and stdout is line buffered
bneq l3523
pushl stdout+FBUF
calls $1,_fflush
l3523:
ret
erefinaf:
movw $EREFINAF,_perrno
moval error,PC(fp) #error return
ret
#
# iosync insures that a useable image is in the buffer window
#
_iosync:
.word R6
cvtwl FUNIT(r7),r6 #r6 has FUNIT flags
bbc $fREAD,r6,eread #error if not open for reading
bbc $fSYNC,r6,l3515 #check for already synced
bbs $fEOF,r6,epeof #error if past EOF
bicw2 $SYNC,r6 #clear unsynced flag
pushl FBUF(r7) #stream
pushl $1 #number of items to read
pushl FSIZE(r7) #data size
pushl r7 #ptr to input window
calls $4,_fread
movl FBUF(r7),r0 #check for EOF
bbs $ioERR,FLAG(r0),epeof
bbs $ioEOF,FLAG(r0),eof
bbc $fTEXT,r6,l3514 #check for text processing
bicw2 $EOLN,r6 #check for EOLN
cmpb (r7),$linefeed
bneq l3514
movb $blank,(r7) #blank out linefeed
bisw2 $EOLN,r6
l3514:
movw r6,FUNIT(r7) #update status flags
l3515:
ret
eof:
bisw2 $EOF,r6 #set EOF
movw r6,FUNIT(r7) #update status flags
pushr $R2|R3|R4|R5 #save registers
movc5 $0,(r0),$0,FSIZE(r7),(r7) #clear buffer to undefined
popr $R2|R3|R4|R5 #restore registers
ret
eread:
movw $EREADIT,_perrno
moval error,PC(fp) #error return
ret
epeof:
movw $EPASTEOF,_perrno
moval error,PC(fp) #error return
ret
#
# push back last char read to prepare for formatted read
#
_unsync:
.word 0
bbc $fREAD,FUNIT(r7),eread #error if not open for reading
bbs $fSYNC,FUNIT(r7),l3526 #push back window char
pushl FBUF(r7)
cvtbl (r7),-(sp)
calls $2,_ungetc
l3526:
ret
#
# flush all active output files
#
_pflush:
.word R6
movl _fchain,r6
beql l3518
l3516:
bbc $fWRITE,FUNIT(r6),l3517
pushl FBUF(r6)
calls $1,_fflush
l3517:
movl FCHAIN(r6),r6
bneq l3516
l3518:
ret
#
# close all active files down to the specified FLEV
#
_pclose:
.word R6|R7
movl _fchain, r7
beql l3520
l3519:
cmpl FLEV( r7),4(ap)
bgtru l3520
bbs $fDEF,FUNIT( r7),l3525
movl FBUF( r7),r6
pushl r6
calls $1,_fclose
jbs $ioERR,FLAG(r6),eclose
l3525:
subl3 $recsze, r7,-(sp)
movl FCHAIN( r7), r7
calls $1,_pfree
tstl r7
bneq l3519
l3520:
movl r7,_fchain
ret
#
# write out the pxp data
#
_pmflush:
.word R6
tstl _pxpbuf
beql l3521
pushal wtopen
pushal monout
calls $2,_fopen
tstl r0
beql l3522
movl r0,r6
pushl r6
pushl $1
pushl _pxpsize
pushl _pxpbuf
calls $4,_fwrite
bbs $ioERR,FLAG(r6),l3522
pushl r6
calls $1,_fclose
bbs $ioERR,FLAG(r6),l3522
l3521:
ret
l3522:
pushal monout
calls $1,_perror
ret