MOEWS@UCONNVM.BITNET (09/09/86)
There's been a lot of UUENCODEd stuff on INFO-ATARI16 recently. If you're
on an IBM system running VM/CMS, you will have two problems with raw UUENCODEd
files:
(1) Trailing blanks will be removed when the files are shipped over
BITNET.
(2) Trailing blanks will be removed if you use VM/CMS Kermit to
transmit the files from VM/CMS to your Atari ST. (Try it and see!)
I have written a version of UUDECODE that ignores the absence of trailing
blanks in a file to be UUDECODEd; using it, I have been able to decode most
of the UUENCODEd stuff that has been posted this summer.
The program is written in assembly language and as a result is much
faster than, for example, the UUENCODE distributed in Franco's starter kit.
It can be assembled with the public domain assembler, AS68, which can be found
in Franco's starter kit or on the Atari BBS. This assembler does not assemble
register shifts, so all the register shifts in the code have been commented
out and hand-assembled to dc.w's.
David Moews MOEWS@UCONNVM.BITNET
---------------cut here----------------
* UUDECODE a file. Copyright (C) 1986 by David Moews.
* Permission to use and redistribute for non-commercial purposes granted.
* ... print an explanatory message ...
pfile pea openm
move.w #pline, -(a7)
trap #1
addq.l #6, a7
* ... get the line ...
lea buffer, a1
move.l #blen, d2
bsr getln
* Open file!
clr.w -(a7) Open for reading
pea buffer
move.w #fopen, -(a7)
trap #1
addq.l #8, a7
* Check for error...
tst.w d0
bmi error
move.w d0, d1 Save handle number
* Skip over first 10 characters ('begin xxx ')
clr.w -(a7)
move.w d1, -(a7)
move.l #10, -(a7)
move.w #lseek, -(a7)
trap #1
add.l #10, a7
tst.l d0
bmi erroro
* Initialize I/O pointers
bsr init
* Get filename (terminated with CR/LF)
lea buf2, a1
gfloop bsr getch
cmp.b #$0d, d7
beq gfdone
move.b d7, (a1)+
bra gfloop
gfdone clr.b (a1)
bsr getch Discard $0a
*
* Open file!
*
clr.w -(a7) R/W file will be created
pea buf2
move.w #fcreat, -(a7)
trap #1
addq.l #8, a7
* Check for error...
tst.w d0
bmi erroro
move.w d0, d2 Save handle number
* ... now the fun begins ...
* GEM uses a0; input buffer pointers a2-a3; output ptrs a4-a5; stack ptr a7
* GEM uses d0; d3=byte count in this line; d4=byte count in this 4-character
* group -or- char count while reading;
* d5=group of 4 characters -or- 3 bytes.
* Scratch in d7.
*
* LINE LOOP
*
* Get count. If 0, we are done.
loop bsr getnn
sub.b #$20, d7 Subtract space
beq done
* Otherwise, get that many characters.
clr.w d3 High byte 0 for "dbf"
move.b d7, d3
subq.w #1, d3 Correct for "dbf"
bsr init3 Reset counters
loop3 bsr getch3
bsr prtch
dbf d3, loop3
bsr skipnl Skip over junk + $0d/$0a
bra loop
*
* Initialize state of 3-characters.
*
init3 clr.w d4
rts
*
* Get another character from a group of 3.
*
getch3 tst.w d4
bne get32
* Read in another group of 4 into d3; reset count to 3.
move.w #3, d4
clr.l d5
*et3l lsl.l #6, d5
get3l dc.w $ed8d
bsr getnn
sub.b #$20, d7
or.b d7, d5
dbf d4, get3l
move.w #3, d4 Set byte count
swap d5 Pattern from [0123] to [2301]
* Get a character out of d3, decrement count in d2, & return!
get32 move.b d5, d7
* rol.l #8, d5
dc.w $e19d
subq.w #1, d4
rts
* Read until we come to a newline; then skip over $0d/$0a.
skipnl bsr getch
cmp.b #$0d, d7
bne skipnl
bra getch
*
* Buffered I/O subroutines. Input buffer pointer a2, end ptr in a3;
* output buffer pointer a4, end prt a5.
*
* Sets up.
init lea inpend, a2
lea inpend, a3
lea outbuf, a4
lea outend, a5
rts
* Get a character in d7.b, EXCEPT that if we are at a newline, get a blank
* instead.
getnn cmp.l a3, a2
bcc getrn
cmp.b #$0d, (a2)
beq getsn
move.b (a2)+, d7
rts
getsn move.b #$20, d7
rts
getrn bsr getrec
bra getnn
* Gets a character in d7.b.
getch cmp.l a3, a2
bcc getr
move.b (a2)+, d7
rts
getr bsr getrec
bra getch
*
* Get a new record into the buffer.
getrec pea inpbuf
move.l #inplen, -(a7)
move.w d1, -(a7)
move.w #fread, -(a7)
trap #1
add.l #12, a7
tst.l d0
bmi error2
beq done No bytes read, file over, done.
* Actual number of bytes read in d0!
lea inpbuf, a2
lea 0(a2, d0.l), a3
rts
*
* Prints byte in d7.b.
prtch cmp.l a5, a4
bcc putr
move.b d7, (a4)+
rts
putr bsr putrec
bra prtch
*
* Dump buffer out.
* Compute number of bytes to put out.
putrec lea outbuf, a5
move.l a5, -(a7)
sub.l a5, a4
move.l a4, -(a7)
move.w d2, -(a7)
move.w #fwrite, -(a7)
trap #1
add.l #12, a7
tst.l d0
bmi error2
lea outbuf, a4
lea outend, a5
rts
*
*
* We come here in case of error.
error bsr pmsg
bra xit
* Here for error after opening 1 file.
erroro bsr pmsg
bsr close1
bra xit
* Here for error after opening 2 files.
error2 bsr pmsg
bsr close1
bsr close2
bra xit
* Here for normal end. Notice that we flush output buffer.
done bsr putrec
bsr close1
bsr close2
xit clr.w -(a7)
trap #1
*
pmsg pea msg
move.w #pline,-(a7)
trap #1
addq.l #6,a7
rts
*
close1 move.w d1, -(a7)
move.w #fclose, -(a7)
trap #1
addq.l #4, a7
rts
*
close2 move.w d2, -(a7)
move.w #fclose, -(a7)
trap #1
addq.l #4, a7
rts
*
*
*
* This subroutine reads a line of input into the buffer at a1.
* Maximum buffer length should be passed in d2. Actual count is
* returned in d1. The buffer should have one more byte than d2
* (to allow for a zero at the end.)
getln movem.l d0/a0, -(a7)
* Clear char count
clr.l d1
glloop move.w #conine,-(a7)
trap #1
addq.l #2, a7
* A BS?
cmp.b #$08, d0
beq bs
* A CR?
cmp.b #$0d, d0
beq crret
* Just a plain character ... are we at EOL?
cmp.l d1, d2
* Yes, ignore it.
beq glloop
* Otherwise, store it...
move.b d0, 0(a1, d1.l)
addq.l #1, d1
* ... and echo.
bsr echo
bra glloop
* A BS --- are we at start of line?
bs tst.l d1
* If so, ignore keystroke.
beq glloop
* Otherwise, decrement counter...
subq.l #1, d1
* ... print BS, space, BS to wipe out char
move.b #$08, d0
bsr echo
move.b #$20, d0
bsr echo
move.b #$08, d0
bsr echo
bra glloop
* A CR --- echo & return.
crret bsr echo
move.b #$0a, d0
bsr echo
clr.b 0(a1, d1.l)
movem.l (a7)+, d0/a0
rts
*
*
* Echo --- echoes a character in d0 to the screen. Destroys d0 & a0.
echo move.w d0, -(a7)
move.w #conout, -(a7)
trap #1
addq.l #4, a7
rts
*
*
*
openm dc.b 'Enter filename to read: '
dc.b 0
msg dc.b 'TOS error occurred!', 13, 10
dc.b 0
buffer ds.b 51
buf2 ds.b 51
blen equ 50
* Buffer for reading from file
inpbuf ds.b $400
inpend ds.b 0
inplen equ $400
* ... and for writing ...
outbuf ds.b $400
outend ds.b 0
outlen equ $400
* Codes for GEMDOS
conout equ $02
rawcon equ $06
conine equ $07
pline equ $09
fcreat equ $3c
fopen equ $3d
fclose equ $3e
fread equ $3f
fwrite equ $40
lseek equ $42
end