                name    UUD
                page    55,132
                title   'UUDECODE.ASM'
;
; UUDECODE.ASM -- UUDecodes a UUEncoded Binary File
;
; Copyright (C) 1988, by Theodore A. Kaldis
;
; To assemble and link this program into the executable UUDECODE.COM:
; (It will NOT run assembled as an .EXE program!)

;               MASM UUD;
;               LINK UUD;
;               (If you just have EXE2BIN:
;                 EXE2BIN UUD
;                 REN UUD.BIN UUDECODE.COM (or whatever)
;               (If you have Public Domain EXE2COM or equivalent:
;                 EXE2COM UUD
;                 REN UUD.COM UUDECODE.COM (or whatever)
;               (Delete the .OBJ file)

; See version 1.1 for .EXE equivalent.

Comment ~
v2.0, 10 Mar 91
- Keith Petersen says we must handle "begin 0600 foobar.arc" type
  headers .. which we surprisingly can't!
  He found the bug:
|David, I found the bug in TOADUU19's uudecode.  I added one line to the
|source code and changed a comment which said that AH already had a
|space in it.
|
|Here's the fix:
|
|;Put a space into AH for fast comparisons
|       mov     ah,' '
|Strip_Spc:

- He also wanted file overwrite protection like TOADXX, so I added that
  as well.  New command line parm (/o or /O) to force overwrite if
  file exists.  Else abort without overwrite.

- He then found a bug in the "no filename" handling.  I added usage
  before the filename prompt.

- While I'm here, tightened up error msg writing a little (preceding
  and following all msgs with CR/LF, etc.)

v1.8, 5 Jul 89

Thanks to Karl-L. Noell <NOELL%DWIFH1.BITNET@CUNYVM.CUNY.EDU>
for a bug report:

|  When I call up UUE12 or UUD17 without filename, a prompt appears:
|  Input path/file:
|  but answering to that prompt always yields the message
|  "Input file error."

Karl-L's right .. stupid .. donno how I missed it.  Fixed.

Added a little logo at the end (overrun by buffers) just to identify
the program.

Toad Hall
~

;v1.7, 9 Nov 88
; - Versions since 1.3 BROKE (a new Truncated line test).
;   Trying again.
; - Handling headers, tailers, truncated lines ok.
; - Moving some start-up data and code down into buffer space
;   just as an exercise.
; - Previously cut down input buffer size to limit buffer requirements.
;   However, since DOS needs 64Kb to load a .COM file anyway,
;   might as well use the entire 64Kb segment allocated us.

;(notes on versions 1.4 thru 1.6 discarded.)

;v1.3, 7 Sep 88
; - Tightened up seeking for 'begin' and 'end'.
; - Added 'start' error.
; - Tightened up line reading, uudecoding a little.
; - made console/error msgs REALLY go to standard ErrOut device (2)
; - Renamed to UUD13.ASM (differenciate from UUE, UU).

;V1.2, 6 Sep 88
; - Changing to .COM format.
; - moved a bunch of buffers (file names, input and output buffers)
;   to be just pointers at code end (not taking up file space).
; - Reduced max file read from 0FE00H to 0F000H (to stay within 64Kb
;   for program and buffers).

;V1.1, 6 Sep 88
; Toad Hall Tweak
; - General tightening.
; - Added comments.
;
;
; David Kirschbaum
; Toad Hall
; kirsch@braggvax.ARPA

;-------------------------------------------
CR              EQU     0DH
LF              EQU     0AH
SPC             EQU     20H
FALSE           EQU     0
TRUE            EQU     NOT FALSE
;-------------------------------------------
CSEG    SEGMENT PARA PUBLIC 'CODE'
        ASSUME  CS:CSEG,DS:CSEG, ES:CSEG

        org     0
cseg_ofs        label   byte            ;fake out MASM                  v1.9
        org     80H

cmd_tail        label   byte            ;v1.8

        org     100H

;-------------------------------------------
Uudecode        PROC    near
        jmp     Start           ;jump over data

;This data will be used during the uudecode run.

err_inp         DB      'Input file error.'
ERR_INP_LEN     EQU     $-err_inp
err_out         DB      'Output file error.'
ERR_OUT_LEN     EQU     $-err_out
err_begin       db      'start not found.'
ERR_START_LEN   EQU     $-err_begin

err_end         DB      'End not found.'
ERR_END_LEN     EQU     $-err_end

exist$          db      ' exists. Aborting!'                            ;v2.0
EXIST$_LEN      equ     $ - exist$                                      ;v2.0

inp_handle      DW      0
out_handle      DW      0
uuptr           DW      UUBUFF          ;points at next byte in uuencoded
                                        ; input buffer UUBUFF
uuEndptr        DW      UUBUFF          ;points beyond uuencoded data
                                        ; (e.g., buffer end)
outptr          DW      OUT_BUF         ;pointer to binary output buffer
                                        ; (where to stuff NEXT uudecoded byte)

overwrite       db      FALSE           ;is set to true for overwriting v2.0

;-------------------------------------------

Start:
        call    Init                    ;cmd line parsing, file opening

;v1.7 If we make it back, all's ok.
;We should have input file opened.

        call    Read_File               ;do the initial read

Get_Out_Fil:
        mov     di,offset OUT_BUF       ;clear DI
        call    Get_Line                ;read a line of input

;Look for uuencoded file's 'begin'
;(Don't like this very much .. could be stuck here until we've gone
;through the entire doggone file!  Oh, well ..it works anyway..
;(Also gobbles up any headers or other garbage at file start.)
;Tried a 'CMPSB'  or 'SCASB' of the input buffer against a 'begin'
;in our own code space, but it was a mess!

        lodsw                           ;snarf 2 plaintext chars
        cmp     ax,'eb'                 ;'be'?
        jne     Get_Out_Fil             ;nope, next line
        lodsw                           ;next 2
        cmp     ax,'ig'                 ;'gi'?
        jne     Get_Out_Fil             ;nope, next line
        lodsw                           ;next 2
        cmp     ax,' n'                 ;'n '?
        jne     Get_Out_Fil             ;nope, next line

        mov     di,offset OUT_FIL       ;to output buffer

;Put a space into AH for fast comparisons
        mov     ah,' '
Strip_Spc:

;Gobble spaces until we hit the mode number after 'begin'
        lodsb
        cmp     al,ah                   ;space?
        jbe     Strip_Spc               ;gobble spaces, tabs, ctrl chars

Strip_Num:
;Hit the number, now gobble until the space after number
        lodsb
        cmp     al,ah                   ;space?
        jne     Strip_Num               ;gobble until space

;v1.7 now gobble any spaces between number and name ... sigh ...
Strip_Spc2:
        lodsb
        cmp     al,ah                   ;space?
        jbe     Strip_Spc2              ;gobble until real char

;We should now be at the first char of the original target's filename.
;Move output filename from LINE_IN buffer to our output filename buffer.
;Since LINE_IN has been padded with spaces, a space will indicate
;name end.
Get_Out:
        cmp     al,ah                   ;space means done
        je      Out_Fin                 ;yep, name end
        stosb                           ;input byte > OUT_FIL filename buff
        lodsb                           ;next filename char
        jmp     Get_Out                 ;and keep going

;-------------------------------------------
Out_Fin:
        mov     dx,offset OUT_FIL       ;output filename buffer
        xor     cx,cx                   ;normal file attribs (R/W)
        mov     [di],cl                 ;AsciiZ output filename

;v2.0   User requested overwrite protection for the output filename.
;       Ok .. let's check for output filename existence before we
;       do the create.

        cmp     overwrite,TRUE          ;"-o" commandline switch?
        jz      Out_Create              ;yep, no checking

        mov     ah,4EH                  ;find first
        int     21H
        cmp     al,2                    ;file not found?
        jz      Out_Create              ;fine, doesn't exist
        cmp     al,18                   ;no more files to be found?
        jz      Out_Create              ;fine

;v2.0 File exists.  Error message, die.
;     DI -> filename AsciiZ 0
;     DX -> filename 1st char

        mov     cx,di                   ;last char
        sub     cx,dx                   ;- first char = chars to write
        call    Say_Error               ;display filename

        mov     dx,OFFSET exist$        ;'File exists'
        mov     cx,EXIST$_LEN           ;msg length
        mov     al,5                    ;fake "Access denied" errorlevel
        jmp     Fatal_Error             ;display, terminate


Out_Create:                             ;v2.0
;End of v2.0 change

        mov     ah,3Ch                  ;create output file
        int     21h
        jnc     Out_Open                ;went ok
         jmp    Out_Err                 ;output file create error


;-------------------------------------------
Out_Open:
        mov     out_handle,ax           ;remember output file handle
        mov     di,offset OUT_BUF       ;prepare to clear outptr
New_Line:
        call    Get_Line                ;read in uuencoded line

;First char is nr of binary bytes used to produce this line. (Asciified)
;If there's an empty last line, it'll just be a space or '`'
        lodsb                           ;snarf uuencoded binary byte count
        or      al,al                   ;empty line?
        jz      Prog_End                ;yep

        mov     bx,2020H                ;a handy constant
        sub     al,bl   ;20H            ;Deasciify
        or      al,al                   ;null?
        je      Prog_End                ;yep, must be done

;v1.7 keeping line's binary byte count in BP
        xor     ah,ah                   ;clear msb
        mov     bp,ax                   ;BP=binary byte count

;uuencoded stuff (input) is in 'quads' (4-char packets),
;binary output is in 'hunks' (3 byte packets)
;4 chars = 3 bytes
NN_0:
        mov     cx,0604H                ;handy constant
                                        ;CL=4, CH=6

        lodsb                           ;quad[1]
        mov     ah,al                   ;AH=quad[1]
        lodsb                           ;AL=quad[2]
        mov     dl,al                   ;save quad[2]
        sub     ax,bx                   ;remove standard offset

        shl     ah,1                    ;quad[1] SHL 2
        shl     ah,1                    ;(faster this way)
        shr     al,cl                   ;quad[2] SHR 4
        or      al,ah                   ;shifted quad[2] OR shifted quad[1]
        stosb                           ;=hunk[1], stuff in OUT_BUF
        dec     bp                      ;decr binary byte ctr
        jz      New_Line                ;uuencoded line is done

        mov     ah,dl                   ;AH=unshifted quad[2]
        lodsb                           ;AL=quad[3]
        mov     dl,al                   ;save quad[3]
        sub     ax,bx                   ;remove standard offset

        shl     ah,cl                   ;quad[2] SHL 4
        shr     al,1                    ;quad[2] SHR 2
        shr     al,1                    ;(faster this way)
        or      al,ah                   ;shifted quad[3] OR shifted quad[2]
        stosb                           ;=hunk[2], stuff in OUT_BUF
        dec     bp                      ;decr binary byte ctr
        jz      New_Line                ;uuencoded line is done

        mov     ah,dl                   ;AH=unshifted quad[3]
        lodsb                           ;AL=quad[4]
        sub     ax,bx                   ;remove standard offset

        mov     cl,ch                   ;6
        shl     ah,cl                   ;quad[3] SHL 6
        or      al,ah                   ;shifted quad[4] OR shifted quad[3]
        stosb                           ;=hunk[3], stuff in OUT_BUF
        dec     bp                      ;decr binary byte ctr
        jnz     NN_0                    ;uuencoded line not done
        jmp     short New_Line          ;line done, get new line

;-------------------------------------------
;Now we look for the uuencoded file's 'end'.
;We'll write out what we've got, even if we don't find the 'end'.

Prog_End:
        call    Get_Line                ;should be file's last line
        lodsw                           ;load next 2 chars
        cmp     ax,'ne'                 ;'en'?
        jne     End_Err_C               ;'No end found'
         lodsb
         cmp    al,'d'
         je     File_End                ;ok, got the 'end'
End_Err_C:
        call    End_Err                 ;say we had an end error
File_End:
        call    Write_File              ;do our final output write
;Seems there's no need to close files .. DOS must do it!
File_End_X:
        mov     ah,4Ch                  ;terminate, ERRORLEVEL ?
        int     21h
Uudecode        endp

;-------------------------------------------
;Reads in a line of uuencoded text
;Didn't like the original logic here (how it physically looks for a CR (0DH)
;as an End of Line indicator (EOL), then gobbles until a LF (0DH).
;Unix text and uuencoded files only have LFs as EOL,
;MACs only have CR EOLs (I think).
;Well, we're handling CR/LF and LF EOLs, and that'll do for now.

;The first char of a uuencoded line is usually an 'M' (ASCII 77).  This is
;the nr of binary bytes used to create this uuencoded line (Asciified).

Get_Line        PROC    NEAR
        mov     si,uuptr                ;current raw input buffer psn

;This is looped to (from below) if the line was garbage (e.g., some sort
;of file header.  It refreshes the outbuf pointer to buffer start,
;and sets up the uuencoded line buffer LINE_IN anew.

Flush_Lin:
        mov     outptr,di               ;save outbuf ptr in outptr
                                        ;for Write_File test

;BP holds the constant 'maximum line length'.
;I never heard of a uuencode that used lines longer than 60 bytes,
;plus length byte and CR/LF.
        mov     bp,80                   ;max allowable uuencoded line len

;Prepare our uuencoded line buffer LINE_IN for transfer of a line.
;Remember, this same sequence is used to get the uuencode protocol's
;first line ('begin 6xx filename.typ'),normal uuencoded lines,
;and the last uuencode protocol line ('end').
;We're preparing an 80-char line (maximum allowed).

        mov     di,offset LINE_IN       ;uuencoded line buffer start
        xor     ax,ax
        stosw                           ;clear first 2 bytes
        mov     cx,(78/2)               ;clear remaining 78 bytes       v1.9
        mov     ax,2020H                ;fill with spaces
        rep     stosw
        mov     di,offset LINE_IN       ;uuencoded line buffer start

Next_Chr:
        cmp     si,uuEndptr             ;hit end yet?
        jb      Not_Mt                  ;not empty yet
         call   Write_File              ;write our binary output (if any)
         call   Read_File               ;read more uuencoded input
Not_Mt:
        lodsb                           ;snarf uuencoded line char
        cmp     al,96                   ;special '`' in place of spaces
        jne     Not_Hi                  ;wasn't a space substitute
         mov    al,' '                  ;replace with space
         jmp    short Was_Space         ;and skip the next test

;We check for both CR End-Of_Line (EOL) and LF EOL.                     v1.9
;(This handles DOS and Unix files.)

Not_Hi: cmp     al,CR                   ;CR means line end
        je      Eol_CR                  ;end of line, got line
        cmp     al,LF                   ;How about Unix EOL?
        je      Eol_LF                  ;Yep, was Unix EOL, got line
Was_Space:
        stosb                           ;stuff uuencoded line char
        dec     bp                      ;count down allowable length
        jnz     Next_Chr                ;Ok, not yet

;This line is longer than 80 chars, so it CAN'T be a uuencoded line.
;Continue to gobble it up, throwing it away, until EOL,
;then flush and continue.
;This only happens for headers.  We never hit trailers at all.

Strip_Head:
        cmp     si,uuEndptr             ;beyond uubuf data?
        jb      Strip_NoRead            ;nope
         call   Read_File               ;refill the uubuf
Strip_NoRead:
        lodsb                           ;look for a LF
        cmp     al,LF                   ;LF yet?
        jne     Strip_Head              ;nope, keep going w/this line

        mov     di,offset OUT_BUF       ;clear DI to clear outptr
        jmp     Flush_Lin               ;EOL, keep working thru raw
                                        ;input buffer

;-------------------------------------------
;Hit CR, got a uuencoded line (DOS files).
;SI -> LF just past the CR.

Eol_CR:
        inc     si                      ;bump raw input buffer ptr past LF

;Hit LF EOL (Unix files).
;SI -> next raw buff char.

Eol_LF:
        mov     uuptr,si                ;remember current raw buff ptr
        mov     di,outptr               ;restore binary output ptr
        mov     si,offset LINE_IN       ;ptr to inbuffer start
        ret                             ;done

Get_Line        ENDP

;-------------------------------------------
;Write a chunk of uudecoded data (if any) to output file.
Write_File      PROC    NEAR

        mov     dx,offset OUT_BUF       ;output binary buffer start
        mov     cx,dx                   ;prepare to reinit outptr
        xchg    cx,outptr               ;outptr=output buffer start,
                                        ;CX=outptr
        sub     cx,dx                   ;-buffer start=buffer byte count

;IF CX=0, there's no uudecoded data to write, just exit.
;If CX went below 0 (e.g., outptr pointed BELOW OUT_BUF start),
;we have an error of some sort (my code logic?).
;Ignore that also.  It'll get cleaned up later.

        jbe     Write_Good              ;error
         mov    bx,out_handle           ;output file handle
         mov    ah,40h                  ;write to file/device
         int    21h
         jb     Out_Err                 ;write error
Write_Good:
        ret                             ;write done

;Output file write error
Out_Err:
        mov     dx,OFFSET err_out       ;'Output file write error'
        mov     cx,ERR_OUT_LEN          ;msg length
        jmp     short Fatal_Error       ;common code, error value in AL

Write_File      ENDP

;-------------------------------------------
;Read a chunk of input (uuencoded) data into our uuencode buffer.
;I don't think we'll EVER try to read past EOF (since the 'end' line
;should've been detected and program terminated).
;Let's assume that 'read past EOF' is an error of some sort and die.
;('Coding by trial and error')

Read_File       PROC    NEAR

        mov     dx,offset UUBUFF        ;read into uuencode input buffer
        mov     cx,offset UU200         ;code space - 200H stack bytes
;v1.9   not     cx                      ;= remaining segment memory
        mov     bx,inp_handle           ;input file handle
        mov     ah,3Fh                  ;read from file/device
        int     21h
        jb      Inp_Err                 ;failed
        or      ax,ax                   ;read anything?
        jz      Read_EOF                ;nope, EOF

        mov     si,dx                   ;point to input UUBUFF start
        add     ax,si                   ;chars read+UUBUFF start
        mov     uuEndptr,ax             ;points beyond last UUBUFF char
        ret                             ;read done

Read_EOF:

;-------------------------------------------
;Input file read error.  Error value in AL
Inp_Err:
        mov     dx,OFFSET err_inp       ;'Input file error'
        mov     cx,ERR_INP_LEN          ;msg length
;Common code added here
Fatal_Error:
        push    ax                      ;save error in AL
        call    Say_Error               ;common code
        pop     ax                      ;restore error in AL
        jmp     File_End_X              ;terminate

Read_File       ENDP

;-------------------------------------------
;Unexpected End of File.  (No 'end')
End_Err         PROC    NEAR

        mov     dx,OFFSET err_end       ;'End not found'
        mov     cx,ERR_END_LEN          ;msg length
Say_Error:                              ;common code
        push    dx                      ;v2.0
        push    cx
        mov     dx,offset crlf          ;Precede all err msgs w/CR/LF   v2.0
        mov     cx,CRLF_LEN
        call    ErrOut                  ;display CR/LF
        pop     cx                      ;restore orig msg len           v2.0
        pop     dx                      ;ptr to msg                     v2.0
        call    ErrOut                  ;display it
        mov     dx,offset crlf          ;Follow all err msgs w/CR/LF    v2.0
        mov     cx,CRLF_LEN

ErrOut:
        mov     bx,2                    ;Std ErrOut handle
        mov     ah,40h                  ;write to file/device
        int     21h
        ret

End_Err         ENDP


;using pointers beyond runtime code and/or code end for various buffers.
;This does NOT take up any space in our program.

                EVEN

;v1.7 LINE_IN is not used until after Init,
;so it can overwrite this code and data.
LINE_IN equ     $                       ;80 bytes long

;Some start-up data moved down here to minimize memory requirements.
msg_v1          DB      CR,LF,'This Program Requires DOS Version 2.0 '
                DB      'or higher.'
crlf            db      CR,LF,'$'
CRLF_LEN        EQU     2                                       ;v2.0
pr_inp          DB      CR,LF,'Input path/file:  '
PR_INP_LEN      EQU     $-pr_inp
no_action       db      'No action'
NO_ACTION_LEN   equ     $-no_action

;v1.7 Some start-up code.
Init    proc    near

;First make sure we have DOS 2.0 or higher, or handles won't work.
        mov     ah,30h                  ;get DOS version
        int     21h
        cmp     al,2                    ;2.0 or above?
        jae     Chk_CmdLine             ;yep, ok
         mov    dx,OFFSET msg_v1        ;'DOS 2.0 or above'
Msg_Die:
         mov    ah,9                    ;display string
         int    21h
         mov    ax,4C01H                ;terminate, ERRORLEVEL 1
         int    21H

;Now check cmd line for uuencoded source file.
Chk_CmdLine:
        call    Parse_CmdLine           ;get cmdline target filename    v1.8
        jnc     Open_Inp_Fil            ;fine, got one                  v1.8
                                        ;DI -> AsciiZed filename
                                        ;0 terminator.

;Let's be nice and prompt the user for an input filename
;v1.8   using normal buffered keyboard input:

;v2.0   First, display usage to the dummy.
        mov     dx,offset usage$        ;'Usage: '
        mov     cx,USAGE_LEN            ;nr chars to display
        call    Say_Error               ;display to STDERR

        mov     dx,OFFSET pr_inp        ;'Input/file name:' prompt
        mov     cx,PR_INP_LEN           ;nr chars to display
        mov     bx,2                    ;Std ErrOut handle (always to con)
        mov     ah,40h                  ;write to file or device
        int     21h

;Now get the user kbd input:

        mov     di,offset cmd_tail-1    ;1 byte before PSP cmdline      v1.8
        mov     byte ptr [di],80        ;tell DOS max of 80 chars       v1.8
        mov     dx,di                   ;DX -> buffer                   v1.8
        mov     ah,0AH                  ;buffered kbd input svc         v1.8
        int     21H
        call    Parse_CmdLine           ;parse the input                v1.8
        jnc     Open_Inp_Fil            ;got input (already AsciiZed)   v1.8
                                        ;try to open                    v1.8
                                        ;DI -> AsciiZ 0                 v1.8
;Okay, he doesn't wanna play...
         mov    dx,offset no_action     ;'No action'                    v2.0
        mov     cx,NO_ACTION_LEN        ;length                         v2.0
        mov     al,1                    ;ERRORLEVEL 1                   v2.0
        jmp     Fatal_Error             ;display msg, die               v2.0


Open_Inp_Fil:
        mov     dx,offset INP_FIL       ;input file name buffer
        mov     ax,3D00h                ;open file
        int     21h
        jb      Open_Die                ;failed, terminate w/error
         mov    inp_handle,ax           ;save input file handle
         ret                            ;go uudecode

Open_Die:
         jmp    Inp_Err                 ;input file open error, die
Init    endp


;v1.8 Command line processing subroutine

Parse_CmdLine   proc    near

        mov     si,offset cmd_tail      ;move cmd line parm
        mov     di,offset INP_FIL       ;to our filename buffer
        cld                             ;insure fwd
        lodsb                           ;cmd line length byte
        or      al,al                   ;nothing there?
        jz      PC_NoInput              ;yep, nothing there

        mov     ah,20H                  ;get a handy space
Strip_Ct:
        lodsb                           ;next cmd line char
        cmp     al,ah                   ;gobble leading spaces,tabs, etc.
        jbe     Strip_Ct
Ct_Char:
        cmp     al,ah                   ;ctrl char? (e.g., CR)
        jbe     PC_Input                ;yep, done

;v2.0   Check for a "-o" switch on command line

        cmp     al,'/'                  ;this kind of switch?
        jz      GotSwitch               ;yep
         cmp    al,'-'                  ;switch?
         jnz    NotSwitch               ;nope, must be name char
GotSwitch:
        mov     dx,ax                   ;save this char a second
        mov     ax,[si]                 ;snarf next 2 chars
        cmp     al,'?'                  ;-? or /?                       v2.0
        jz      JustHelp                ;yep, help and die              v2.0

        and     al,5FH                  ;mask 1st char to uppercase
        cmp     ax,' O'                 ;O and space means switch
        mov     ax,dx                   ;restore in case not
        jnz     NotSwitch               ;nope, must be name

;v2.0   We have the overwrite switch

        not     overwrite               ;toggle flag to TRUE
        inc     si                      ;bump past 'o'
        inc     si                      ;and past space
        lodsb                           ;next char should be name

NotSwitch:
;end of v2.0 changes
        stosb                           ;stuff filename byte
        lodsb                           ;snarf next cmdline char
        jmp     short Ct_Char           ;and loop

PC_NoInput:
        stc                             ;no input, return CF set
        ret

PC_Input:
        mov     byte ptr [di],0         ;Asciize filename input
        clc                             ;got input, return CF clear
        ret

JustHelp:
        mov     dx,offset usage$
        jmp     Msg_Die                 ;display, terminate

Parse_CmdLine   endp


                EVEN

;INP_FIL is used by Init startup, so it must sit below the code.
INP_FIL equ     $                       ;80 bytes long,
                                        ; input filename buffer.
                                        ; Overwrites OUT_FIL buffer
                                        ; and uuencode buffers.

;OUT_FIL, OUT_BUF, and UUBUFF aren't used until AFTER Init completes.
;They can overwrite Init code, startup data, INP_FIL filename buffer, etc.
;However, UUBUFF and LINE_IN ARE used to get the output filename OUT_FIL),
; so UUBUFF and LINE_IN can't overwrite OUT_FIL.

;LINE_IN needs 80 bytes:
OUT_FIL equ     LINE_IN + 80            ;15 bytes long,
                                        ; output filename buffer.
                                        ; Sits below LINE_IN,
                                        ; overwrites Init code/data.
OUT_BUF equ     LINE_IN + 80            ;80 bytes long,
                                        ; uudecoded data buffer.
                                        ; Sits below LINE_IN,
                                        ; overwrites OUT_FIL filename
                                        ; and Init code/data.
;OUT_BUF needs 80 bytes
UUBUFF  equ     OUT_BUF + 80            ; uuencoded file read buffer.
                                        ; Sits below OUT_BUF,
                                        ; uses remaining code space.
;UU200  equ     NOT(UUBUFF + 200H)      ;200H bytes oughtta be enough   v1.9
UU200   equ     (offset cseg_ofs - offset UUBUFF) - 200H
                                        ;for the stack.

logo    db      'UUDECODE v2.0',0
        db      'Originally by Theodore A. Kaldis',0
        db      'Thoroughly rehacked by David P Kirschbaum, Toad Hall',0

usage$  db      'UUDECODE [-?][-o] [d:][\path\]binary.UUE <RETURN>',CR,LF
        db      'Using the filename.typ in the "begin" line,',CR,LF
        db      'produces uudecoded filename.typ on current drive\path',CR,LF
        db      '(providing filename.typ doesn''t already exist).',CR,LF
        db      '-o switch forces overwrite of existing filename.typ',CR,LF
        db      '-? produces this help message.'

USAGE_LEN       equ     $ - offset usage$
        db      CR,LF,'$'                                       ;v2.0
CSEG    ENDS
        END     Uudecode
