home *** CD-ROM | disk | FTP | other *** search
- ;ZDIR .ZIP directory utility
- ;From a disassembly and hack of ADIR.EXE
-
- ;v1.3c Bug: I'd written code to handle no cmdline parms at all,
- ; but failed to test it! Turns out system locks up!
- ; Thanks to FAAR RBBS for alerting me. Sloppy testing procedures.
-
- ;v1.3b Bug: Forgot the added "-v" verbose switch as the FIRST PSP
- ; cmdline argument would blow away using our PSP FCB's to get
- ; the parsed member filename.
- ; Using _Args (from KEGELUNX unix-like cmdline parsing)
- ; to handle the -v switch anywhere on cmdline.
- ; (Affects Parse_CmdLine only.)
-
- ;v1.3a 23 Mar 89
- ; - Adding file comment display to verbose mode.
- ; - Because of the occasional padding (by XMODEM) of garbage to the
- ; end of a file, we're back to reading a full 256 bytes at the
- ; ZIP file end to find that end structure (149 bytes for the largest
- ; likely ENDDIR structure, plus the padding to the next 128 boundary).
- ; If you don't HAVE any of these files, change ENDOFS back to 149.
-
- ;v1.3 22 Mar 89
- ; - Adding verbose display (a -v switch).
- ; Cribbing code from QBARCV3.ASM (my improvements on QBARV2.ASM,
- ; a utility for RBBS ARC/PAK displays).
- ; Usage: ZDIR -v foob (yep, -v must be first parm)
-
- ;v1.2 21 Mar 89
- ; - Missed the obvious .. the very last structure in a ZIP file
- ; (call it ENDDIR) contains a pointer to the central directory.
- ; Since the only variable length fields in that last structure
- ; are fairly short (zip comments, etc.), it should be MUCH smaller.
- ; We won't need that huge 5Kb SWAG for the initial directory read.
- ; Cutting buffer down to 128 bytes, reading in ENDDIR to get that
- ; central directory pointer, and then going right to central directory.
- ; Since the max possible ZIP file comment (in ENDDIR) is 7FH bytes,
- ; the max possible ENDDIR would be 7FH + 22 (normal structure size)
- ; or 149 bytes (ENDOFS).
- ; - Moved initial cmdline parsing down to code end
- ; (just to clean up things)
- ; - Caught a bug .. failed on a single '*' wildcard cmdline parm.
-
- ;v1.1 18 Mar 89
- ; - Added full pathing capabilities for target .ZIP files.
- ; - Added ambiguous member screening (e.g., search FOOB.ZIP
- ; for just *.ASM files).
- ; - Cleaned up the kludgey ADIR wildcard finds with all its
- ; multiple DTAs, etc.
- ; - Still no way to test for member filename paths.
-
- ;Original ADIR.EXE fixes:
- ; - Fixed bug that never closed any files!
- ; - Changed to .COM format, tightened, etc.
-
- ;ZIP functional changes: MANY! I consider this almost a total rewrite
- ;(except for the kludge with wildcard finds from the original ADIR.EXE).
-
- ; - Since the filename length is variable (and may include paths),
- ; the handling, formatting and display is significantly different
- ; than in ADIR.
- ; - Have to put back the ambiguous member parsing.
-
- ;David Kirschbaum
- ;Toad Hall
-
- FALSE equ 0
- TRUE equ NOT FALSE
- CR equ 0DH
- LF equ 0AH
- STDOUT equ 1
- STDERR equ 2
- ENDOFS equ 256 ;149 ;enough for largest possible v1.2
- ;ZIP end directory structure. v1.2
- ;(to include XMODEM padding) v1.3a
-
- Print macro name ; display a field
- mov dx,offset name
- call PrintS
- endm
-
-
- ;PKZIP central directory structure:
-
- zdirEntry STRUC
- zsig1 db 50H,4BH,01H,02H ;central file header signature 4 bytes
- ;(0x02014b50)
- zVerMade dw ? ;version made by 2 bytes
- zVerExt dw ? ;version needed to extract 2 bytes
- zBitflag dw ? ;general purpose bit flag 2 bytes
- zCmpMeth dw ? ;compression method 2 bytes
- zModTime dw ? ;last mod file time 2 bytes
- zModDate dw ? ;last mod file date 2 bytes
- zCrc32 dw ?,? ;crc-32 4 bytes
- zCmpSiz dw ?,? ;compressed size 4 bytes
- zUncmpSiz dw ?,? ;uncompressed size 4 bytes
- zNameLen dw ? ;filename length 2 bytes
- zExtraLen dw ? ;extra field length 2 bytes
- zFilCmtLen dw ? ;file comment length 2 bytes
- zDskNrPtr dw ? ;disk number start 2 bytes
- zIntAttr dw ? ;internal file attributes 2 bytes
- zExtAttr dw ?,? ;external file attributes 4 bytes
- zHdrOfs dw ?,? ;relative offset of local header 4 bytes
- zFilename db ? ;filename (variable size)
- ;extra field (variable size)
- ;file comment (variable size)
- zdirEntry ENDS
-
- ; End of central dir record:
-
- zdirEnd STRUC
- zEndSig db 50H,4BH,05H,06H ;end of central dir signature 4 bytes
- ;(0x06054b50)
- zDskNr dw ? ;number of this disk 2 bytes
- zDirDsk dw ? ;number of the disk with the
- ;start of the central directory 2 bytes
- zDskNrEntry dw ? ;total number of entries in
- ;the central dir on this disk 2 bytes
- zDirNrEntry dw ? ;total number of entries in
- ;the central dir 2 bytes
- zDirSiz dw ?,? ;size of the central directory 4 bytes
- zDirOfs dw ?,? ;offset of start of central
- ;directory with respect to
- ;the starting disk number 4 bytes
- zCmtLen dw ? ;zipfile comment length 2 bytes
- zCmt db ? ;zipfile comment (variable size)
- zdirEnd ENDS
-
-
- CSEG segment para public
- assume CS:CSEG,DS:CSEG
-
- org 5CH ;FCB #1
- db ? ;drive val
- fcb1 db 10H dup(?) ;5DH, FCB #1 first char
- fcb2 db 10H dup(?) ;6DH, FCB #2 first char
- org 80H
- nchar db ?
- params db ?
-
- ;program entry point
- org 100H
-
- Zdir proc near
- jmp Start ;skip over runtime data
-
-
- usage db CR,LF,9,9, 'ZDIR version 1.03c, 880327',CR,LF
- db 9,9,'David Kirschbaum, Toad Hall',CR,LF
- db 9,9, 'USAGE: ',9,'ZDIR zipname[.zip] [afn] [-v]',CR,LF
- db 9,9,9,'zipname may be ambiguous (wildcarded)',CR,LF
- db 9,9,9,'afn = ambiguous member file name', CR,LF
- db 9,9,9,'-v = verbose display',CR,LF
- USAGELEN equ $ - usage
-
- ziptyp db '.ZIP'
- ZIPTYPLEN equ $ - ziptyp
-
- msg1 db CR,LF, 9, 9, 9, ' ZIP file: '
- MSG1LEN equ $ - msg1
- msg2 db 'ZIP file not found',CR,LF
- MSG2LEN equ $ - msg2
- msg3 db 'Central directory not found',CR,LF
- MSG3LEN equ $ - msg3
- msg4 db 'ZIP is out of alignment or it''s not a ZIP'
- crlf db CR,LF
- MSG4LEN equ $ - msg4
- CRLFLEN equ $ - crlf
-
- rivvvt db 'Rivvvvt',CR,LF
- RVTLEN equ $ - rivvvt
-
-
- handle dw 0
- flag1 db LOW(TRUE) ;Find First flag v1.3
- verbose db LOW(FALSE) ;verbose display switch v1.3
- znameptr dw 0 ;point past ZIP target file path v1.1
- mnameptr dw 0 ;remember .zFilename start v1.1
- dirNrEntry dw 0 ;central directory file count v1.2
- dirctr dw 0 ;for counting down members v1.3
-
- Comment ~ Looks like:
- +filename.typ 000K / 000K +filename.typ 000K / 000K +filename.typ 000K / 000K
- Comment ends ~
- blankline db ' . K / K . K / K '
- db ' . K / K',CR,LF
- LINELEN equ $ - blankline
-
- ;v1.3 Verbose display data
- ; display lines for verbose
-
- vhdr db CR,LF
- db 'Name Length Stowage SF Size now Date Time CRC '
- db CR,LF
- db '============ ======== ======== ==== ======== ========= ====== ===='
- db CR,LF
- VHDRLEN equ $ - vhdr
-
- vline label byte ;db CR,LF
- vname db 14 dup (' ')
- vlength db ' ' ; length in archive v1.3
- vstyle db ' ' ; compression method
- vfactor db ' xx% ' ; compression factor
- vsize db 10 dup (' ') ; actual file bytes
- vdate db 'dd ' ; creation date
- vmonth db 'mmm '
- vyear db 'yy '
- vtime db 'hh:mm ' ; creation time
- vcrc db 'xxxx' ; crc in hex
- db CR,LF
- VLINELEN equ $ - vline
-
-
- ; final totals line
-
- vthdr db '*Total ' ; ' CPC151A
- vtmbrs db ' '
- vtlen db 8 dup (' '),' '
- db 10 dup (' ')
- vtsf db ' % '
- vtsize db 8 dup (' ')
- db CR,LF ; for tom
- VTHDRLEN equ $ - vthdr
-
- totcmp dw 0,0 ; total of file lengths
- totuncmp dw 0,0 ; total of file sizes
- totmbrs dw 0 ; total number of files
- TOTLEN equ $ - totcmp
-
- ttotcmp dw 0,0
- ttotuncmp dw 0,0
- ttotmbrs dw 0
-
- ;v1.3 ZIP compression types:
-
- zstyles label byte
- db ' Stored' ;0 - The file is stored (no compression)
- db ' Shrunk' ;1 - The file is Shrunk
- db 'Reduced1' ;2 - Reduced with compression factor 1
- db 'Reduced2' ;3 - Reduced with " " 2
- db 'Reduced3' ;4 - Reduced with " " 3
- db 'Reduced4' ;5 - Reduced with " " 4
-
- months db 'Jan Feb Mar Apr May Jun Jul Aug Sep Oct Nov Dec '
-
-
- Zdir endp
-
- Start proc near
-
- call Parse_CmdLine ;parse cmdline for v1.2
- ;target filenames
- jb Jmp_Msg_Term ;failed v1.2
-
- ;Let's get to work
-
- call Find_Zip
- jnc ZipLup_73 ;found the first one
- mov dx,offset msg2 ;'Zipfile not found'
- mov cx,MSG2LEN
- Jmp_Msg_Term:
- jmp Msg_Term ;display, terminate
-
- ZipLup_73:
- call Read_CentralDir ;try to read in file trailer
- jnb Got_Dir ;found it, DS:BX -> directory
-
- mov dx,offset msg3 ;'No central directory'
- mov cx,MSG3LEN
- jmp short Next1 ;right to next ZIP file v1.2
-
- Got_Dir:
- cmp verbose,LOW(TRUE) ;verbose mode? v1.3
- jnz Got_NotVerbose ;nope
- mov dx,offset vhdr ;display verbose header v1.3
- mov cx,VHDRLEN
- call Pr_StdOut
- jmp short MemberLup
-
- Got_NotVerbose:
- call Refresh_LineBuff ;Init formatted display line
-
- MemberLup:
- cmp word ptr [bx],4B50H ;signature?
- jnz Bad_Dir ;nope, bogus
- cmp word ptr 2[bx],0201H ;normal entry?
- jnz Bad_Dir ;nope, bogus v1.2
-
- ;Normal directory entry. Display it.
-
- call Show_FileData ;display entry info
- dec dirctr ;decr nr entries v1.3
- jz Next_Zip ;last entry v1.2
- jmp MemberLup ;next member
-
-
- Bad_Dir:
- mov dx,offset msg4 ;'ZIP is out of alignment'
- mov cx,MSG4LEN ; or not a .ZIP file'
- call Pr_StdOut ;display msg
-
- Next_Zip:
- mov dx,offset crlf ;need a new line
- mov cx,CRLFLEN ;length
- cmp verbose,LOW(TRUE) ;verbose mode? v1.3
- jz Show_Verbose_Totals ;yep, maybe display totals v1.3
-
- mov ax,offset LINEBUFF ;formatted line start
- cmp di,ax ;got any file entries?
- jz Next1 ;nope
- dec di ;back up over the two spaces
- dec di ; from the last file size
- mov dx,ax ;DX'll need it for display
- mov cx,ax ;CX will be nr chars
- mov ax,0A0DH ;CR/LF
- stosw ;stuff
- stosw ;2 CR/LFs
- xchg cx,di ;CX = end, DI = start
- sub cx,di ;end - start = length
- jmp short Next1
-
- ;v1.3 Verbose mode
- Show_Verbose_Totals:
- cmp totmbrs,0 ;any totals?
- jz Next1 ;nope
- call Format_Totals ;yep, format
- ;CX,DX prepared for ...
- Next1:
- call Pr_StdOut ;display line seg or CR/LF
- Next2:
- call Find_Zip ;next .ZIP file
- jnc ZipLup_73 ;found it, loop
-
- cmp verbose,LOW(TRUE) ;verbose mode?
- jnz No_More ;nope
-
- ;v1.3 We've been accumulating overall totals.
- ; Now display them. Gotta move the total totals
- ; into the totals (where Format_Totals expects them).
-
- mov ax,ttotmbrs ;accumulated total mbrs
- cmp ax,dirNrEntry ;just the one ZIP?
- jz No_More ;yep, forget the total totals
-
- mov si,offset ttotcmp ;move total totals
- mov di,offset totcmp ;into totals
- mov cx,TOTLEN SHR 1 ;nr words
- rep movsw
-
- call Pr_CrLf ;down extra line
- call Format_Totals ;format overall totals
- call Pr_StdOut ;display them
-
- No_More:
- mov dx,offset rivvvt
- mov cx,RVTLEN ;fall thru to...
- xor ax,ax ;ERRORLEVEL 0
-
- Msg_Term:
- push ax ;save errorlevel
- call Pr_StdOut ;display error msg
- pop ax
- mov ah,4Ch ;terminate, AL = ERRORLEVEL
- int 21h
-
- Start endp
-
-
- ;SUBROUTINE
-
- Find_Zip proc near
-
- ;We reset our DTA to the default PSP DTA each time through.
- ;The actual ZIP file open uses another one.
-
- mov dx,80H ;use PSP DTA
- mov ah,1AH ;set DTA
- int 21h
-
- cmp flag1,0FFh ;first time thru?
- jne FindNext_162 ;nope
-
- ;First time through
- not flag1 ;set to NOT first time thru
-
- mov dx,offset ziptarget ;DS:DX -> zip target name
- xor cx,cx ;read-only
- mov ah,4Eh ;find first
- int 21h
- jmp short Find_Done
-
- FindNext_162:
- mov ah,4Fh ;find next
- int 21h
- Find_Done:
- jb FindZ_X ;failed, return CF set
- call Move_FileName ;move name in after path
- ;to create full name for open
-
- ;Found target file. Announce, set new DTA, open it.
-
- mov dx,offset msg1 ;'Zip file: '
- mov cx,MSG1LEN
- call Pr_StdOut
- Print ziptarget ;'filename.zip' v1.3
- call Pr_CrLf ;new line
-
- ;We need a new DTA for the file open/read so we don't blow away
- ;the find first/find next stuff in the PSP DTA.
-
- mov dx,offset dta1BA ;DS:DX -> new DTA
- mov ah,1Ah ;set DTA
- int 21h
-
- mov dx,offset ziptarget ;DS:dx -> filename buffer
- mov ax,3D00H ;open file, read only
- int 21h
- mov handle,ax ;save handle
- FindZ_X:
- ret
- Find_Zip endp
-
-
- Move_FileName proc near
-
- mov si,9EH ;FCB #1 +1
- mov di,znameptr ;pointer to after path
- mov cx,13 ;include AsciiZ 0
- rep movsb
- ret
-
- Move_FileName endp
-
-
- ;Reads in file tailer.
- ;Then scans for the unique central directory signature.
- ;On success:
- ; DS:BX -> central directory structure
- ; readlen = nr bytes actually read
- ; CF clear
- ;Else CF set for failure
-
- Read_CentralDir proc near
-
- xor cx,cx ;CX:DX = offset from end
- xor dx,dx ;to very end
- mov bx,handle ;file handle
- mov ax,4202H ;move file pointer to end
- int 21H ;gets file size in DX:AX
- jb RCD_Close ;seek failed
-
- sub ax,ENDOFS ;back up psn.lo
- jnb Read1 ;ok, no problem
- sub dx,1 ;got a borrow, decr psn.hi
- jnb Read1 ;no problem
- xor ax,ax ;sigh .. small file ..
- xor dx,dx ; .. back to very start
- Read1:
- mov cx,dx ;psn.hi
- mov dx,ax ;psn.lo
- mov ax,4200H ;now move from start
- int 21H ;CX:DX point to offset from end
- ;(big) or to start (small)
- jb RCD_Close ;failed, close up
-
- mov cx,ENDOFS ;try to read this much
- mov dx,offset DIRBUFF ;into our directory buffer
- mov di,dx ;DI'll need it in a second
- mov ah,3FH ;read from file/device
- int 21H
- jb RCD_Close ;failed, close up
-
- ;v1.2 First scan the end structure to locate the central directory.
-
- call Sig_Scan ;find the structure start
- jb RCD_InvalidDir ;failed, close and exit
-
- ; ES:DI -> end structure start (the signature)
- ;v1.3a While we have the end structure, let's pick up and display
- ; any ZIP file comment.
- mov cx,[di].zCmtLen ;comment length
- jcxz RCD_NoComment ;nope, forget it
-
- lea dx,[di].zCmt ;DS:DX -> comment
- call Pr_StdOut ;display it.
- call Pr_CrLf ;and a new line
-
- RCD_NoComment:
-
- ; Pick up the central directory file pointer (long integer):
- ; It's a pointer directly to the central directory start.
- ; This will only work for single-disk ZIP files.
-
- mov si,[di].zDirSiz ;save central directory size
-
- mov ax,[di].zDirNrEntry ;nr central dir entries
- mov dirNrEntry,ax ;save it for later
- mov dirctr,ax ;two places
-
- mov dx,[di].zDirOfs ;central directory offset.lo
- mov cx,[di].zDirOfs[2] ;offset.hi
- mov ax,4200H ;move file ptrs from start
- int 21H
- jb RCD_Close ;seek failed, close and exit
-
- mov cx,si ;read central dir size bytes
- mov dx,offset dirbuff ;into our directory buffer
- mov ah,3FH ;read from file/device
- int 21H
- jb RCD_Close ;failed, forget it
-
- mov di,dx ;DI -> dir start
- xor ax,ax ;return AX=0 for ok
- cmp word ptr [di],4B50H ;is it a signature?
- jnz RCD_InvalidDir ;nope
- cmp word ptr 2[di],0201H ;is it a file entry sig?
- jz RCD_Close ;yep, good to go, CF clear
-
- RCD_InvalidDir:
- mov al,11 ;Invalid format
- stc ;insure CF set, AL=error
- RCD_Close:
- mov dx,ax ;save error value (if any)
- pushf ;save flags
- mov ah,3EH ;close file
- int 21H ;(BX = file handle)
- popf ;restore orig flags
- mov ax,dx ;and any error value
- mov bx,di ;if it went well,
- ;DS:BX -> central dir struc
- ret
-
-
- ;v1.2 Subroutine for Read_CentralDir
- ; Scans backwards through buffer for a directory end signature.
- ; Enter with:
- ; SI = second two signature bytes
- ; DX -> buffer start
- ; AX = bytes read
-
- ;We must scan at the byte level (since a member or directory entry
- ;can be ANY length).
-
- Sig_Scan:
- mov di,dx ;ES:DI -> DIRBUFF
- ;(now a ZIP end dir structure)
- add di,ax ;+ bytes read = -> buff end
- mov cx,ax ;bytes read for the scan
- inc cx ;debug for MAX size
- inc cx
- mov ax,4B50H ;scan for first signature char
- ;(same for all structures) v1.2
- mov si,0605H ;2d 2 chars of a directory
- ;end structure signature
- std ;scan from end to start
-
- SS_Lup:
- repne scasb ;ES:DI -> read buffer
- jnz No_Sig ;not found
- jcxz No_Sig ;scanned it all
-
- ;ES:DI -> the byte BEFORE the 50H signature
-
- cmp 2[di],ah ;2d signature byte?
- jnz SS_Lup ;nope, keep searching
- cmp 3[di],si ;last 2 signature bytes?
- jnz SS_Lup ;nope, keep searching
-
- inc di ;bump from that last scasb
- ;DS:DI -> dir structure
- cld ;forwards again to be neat
- clc ;CF clear for success
- ret
-
- No_Sig: cld ;forward again to be neat
- stc ;return CF set for failure
- ret
-
- Read_CentralDir endp
-
-
- ;SUBROUTINE
- ;1 call
- Show_FileData proc near
-
- ;v1.1 Adding tests for cmdline member name testing
- call Member_Test ;see if file is eligible
- jb SF_NextRec ;nope, forget it
-
- push bx
-
- cmp verbose,LOW(TRUE) ;verbose? v1.3
- jnz SFD_NonVerbose ;nope v1.3
- call Show_Verbose ;yep, show verbose v1.3
- jmp short SFD_BumpPtrs
-
- SFD_NonVerbose:
- call Stuff_FileName ;parse, pad at ES:DI
-
- lea si,[bx].zCmpSiz ;compressed size (long int)
- call Stuff_FileSize ;to ES:DI
-
- lea si,[bx].zUncmpSiz ;uncompressed size
- inc di ;adjust line ptr
- call Stuff_FileSize ;stuff uncompressed size
- ; to ES:DI
- cmp di,offset LINEBUFF + LINELEN ;hit end?
- jb SFD_BumpPtrs ;nope
- mov dx,offset LINEBUFF ;display the line
- mov cx,LINELEN ;length
- call Pr_StdOut ;display it
- call Refresh_LineBuff ;refresh dynamic variable
-
- SFD_BumpPtrs:
- pop bx
-
- SF_NextRec:
- ;Now bump our BX pointer to the next entry
- lea ax,[bx].zFilename ;from filename start
- add ax,[bx].zNameLen ;add in name field length
- add ax,[bx].zExtraLen ;and extra field length
- add ax,[bx].zFilCmtLen ;and file comment field length
- mov bx,ax ;should be next record
- ret
-
- Show_FileData endp
-
- ;v1.1 Tests to see if THIS file is eligible (e.g., meets the ambiguous
- ; filename entered on cmdline at startup).
- ; If no such parm, accept it (return CF clear).
- ; If it matches, return CF clear.
- ; If no match, return CF set.
-
- ; While we're here, let's Asciify that stupid ZIP directory file name
- ; for later tests.
-
- Member_Test proc near
-
- mov cx,[bx].zNameLen ;name length
- jcxz MT_Fail1 ;zero .. flunk it!
-
- push di ;save formatted line pointer
-
- lea si,[bx].zFilename ;dirEntry filename
- mov di,si ;start
- dec di ;back it up one
- mov ax,di ;remember new start
- mov dx,cx ;save length
-
- rep movsb ;move it left 1 byte
- mov byte ptr [di],0 ;AsciiZ the name
-
- mov cx,dx ;restore count
- mov si,ax ;new start
- mov mnameptr,ax ;assume no paths
-
- cmp byte ptr 1[si],':' ;a drive separator?
- jnz MT_NoDrive ;nope
- mov ax,2
- add si,ax ;bump past d:
- sub cx,ax ;adjust length counter
- jbe MT_Fail ;zeroed out, flunk it!
-
- MT_NoDrive:
-
- ;Check for directory slashes
- mov di,si ;starting point
- mov al,'\' ;scan for directory slashes
-
- MT_SlashScan:
- repne scasb
- jnz MT_NoSlash ;none
- jcxz MT_Fail ;zeroed out, flunk it!
- mov si,di ;new starting point
- jmp MT_SlashScan ;and try again until all gone
-
- MT_NoSlash:
-
- ;SI now points at first filename char.
-
- mov mnameptr,si ;remember the new address
-
- cmp byte ptr pname1,20H ;empty 2d cmdline parm?
- jz MT_Done ;empty, forget the compares
-
- mov di,offset fcb3 ;ES:DI -> dynamic working FCB
- mov dx,di ;save a sec
- xor ax,ax ;fill with 0's
- mov cx,6 ;clear old 12-byte filename
- rep stosw
- mov di,dx ;ES:DI -> dynamic working FCB
- mov ax,2900H + 00001101b ;parse filename
- ;(strip leading spaces,
- ; don't set drive spec,
- ; change only if valid)
- int 21H
- cmp al,0FFH ;failed?
- jz MT_Fail ;yep
-
- ;We can now compare two expanded file names .. the 2d cmdline parm
- ;and the ZIP file member.
-
- inc di ;skip leading 0 in filename
- mov si,offset pname1 ;possible 2d cmdline parm
-
- MT_CmpLup:
- lodsb ;arg1 char
- or al,al ;hit end?
- jz MT_Done ;yep, done with a match
- mov ah,[di] ;snarf expanded name char
- inc di ;bump expanded filename pointer
- cmp al,'?' ;wildcard? (no test)
- jz MT_CmpLup ;yep, no test
- cmp al,ah ;match?
- jz MT_CmpLup ;yep, continue
-
- MT_Fail: ;no match
- pop di ;restore formatted line ptr
-
- MT_Fail1:
- stc ;return CF set
- MT_X: ret
-
- MT_Done:
- pop di
- clc ;return CF clear for success
- ret
-
- Member_Test endp
-
-
- ;v1.1 ES:DI -> next position on formatted line
- ; zFilename is now AsciiZed
- ; mnameptr contains ptr to original or real zFilename start
- ; (paths stripped)
-
- Stuff_FileName proc near
-
- push di ;save formatted line ptr
-
- mov al,' ' ;assume no paths
- lea si,[bx].zFilename ;dirEntry filename start
- dec si ;adjust for previous backup
- cmp si,mnameptr ;same as member search?
- jz SN_NoPaths ;yep, means no paths
- mov si,mnameptr ;pick up REAL start
- mov al,'+' ;stuff a symbol for paths
- SN_NoPaths:
- stosb ;stuff space or '+'
- mov dx,di ;name start
- add dx,8 ;bump to the dot
-
- SN_Lup: lodsb
- or al,al ;hit AsciiZ 0 yet?
- jz SN_Done ;yep
- cmp al,'.' ;.typ separator?
- jnz SN_NoDot ;nope
- cmp di,dx ;where the dot should go?
- jz SN_NoDot ;yep, put it there
- mov di,dx ; bump to the dot psn
- SN_NoDot:
- stosb ;stuff in formatted line
- jmp SN_Lup
-
- SN_Done:
- pop di ;orig ptr
- add di,14 ;bump to size psn
- ret
-
- Stuff_FileName endp
-
-
- ;SUBROUTINE
- ;2 calls
- Stuff_FileSize proc near
- push bx ;Preserve BX! (dta ptr)
-
- add di,3 ;move to number string end
- push di ;save it (ptr to last digit)
-
- mov ax,[si]
- mov dx,[si+2]
- add ax,3FFh ;div 1024 to get Kb
- adc dx,0
- mov cl,0Ah
- shr ax,cl
- mov cl,6
- shl dx,cl
- add ax,dx
-
- mov si,0Ah
- SFS_Lup:
- xor dx,dx
- div si
- add dl,30H ;asciify
- dec di ;back up the digit pointer
- mov [di],dl ;stuff digit in buffer
- or ax,ax ;number done?
- jnz SFS_Lup ;nope
-
- pop di ;restore line buffer ptr
- add di,3 ;bump past ' / ' or ' | '
- pop bx
- ret
-
- Stuff_FileSize endp
-
-
- ;v1.3 Verbose display functions
- ;v1.3 Format, display single line for each member
- ; On success, return:
- ; CF clear
- ; AL = 0
- ; On error, return:
- ; CF set (because of output write fail)
- ; AL = error code
- ; Preserve BX (buffer ptr)
-
- sign db ' ' ;local variable
- hundred dw 100 ; for computing percentages
-
- Show_Verbose proc near
-
- mov si,mnameptr ;move real member name
- ;(no paths)
- mov di,offset vname ;into formatted line
- mov cx,word ptr 13 ;13 spaces in field
- SV_Lup:
- lodsb ;snarf char
- or al,al ;AsciiZ ending?
- jz SV_5 ;yep
- stosb
- loop SV_Lup
-
- SV_5:
- mov al,' '
- rep stosb ;pad with spaces
-
- ; reduce the size/length to word values
-
- mov si,[bx].zUncmpSiz ; get uncompressed file size
- mov ax,[bx].zUncmpSiz[2]
-
- mov cx,[bx].zCmpSiz ;compressed size
- mov dx,[bx].zCmpSiz[2]
-
- SV_51: or ax,ax ; big number?
- jz SV_52 ; nope, can use it
- shr ax,1 ; yup, divide by two
- rcr si,1
- shr dx,1
- rcr cx,1
- jmp SV_51 ;loop
-
- SV_52:
- mov ax,si ; low word of actual size
- mov sign,' '
- cmp ax,cx ; arc member is larger?
- jb SV_520
- sub ax,cx ; amount saved
- jmp short SV_56
-
- SV_520:
- sub ax,cx
- neg ax
- mov sign,'-'
-
- SV_56:
- mul hundred ; to percentage
- add ax,50
- adc dx,0 ; round up percent
- or si,si ; empty file?
- jnz SV_53
- mov ax,100
- jmp short SV_54
-
- SV_53: div si
- SV_54:
- cmp ax,100 ; archive fouled?
- jbe SV_55
- sub ax,ax
- SV_55:
- mov di,offset vfactor-2 ;format stowage factor
- call Asciify ;display AX
-
- mov al,sign
- mov vfactor,al
-
- mov si,[bx].zCmpMeth ;method of compression
- mov cl,3 ; eight bytes each entry
- shl si,cl
-
- add si,offset zstyles ;point into style table
- mov di,offset vstyle
- mov cx,word ptr 4 ;move as words (8 bytes)
- rep movsw
-
- mov dx,[bx].zCmpSiz[2] ;compressed size.hi
- mov ax,[bx].zCmpSiz ;compressed size
- add totuncmp,ax ;accumulate
- adc totuncmp[2],dx
- mov di,offset vsize ;format file size
- call Asciify_Long
-
- mov dx,[bx].zUncmpSiz[2] ;uncompressed size.hi
- mov ax,[bx].zUncmpSiz ;uncompressed size.lo
- add totcmp,ax ;accumulate
- adc totcmp[2],dx
- mov di,offset vlength ;format file length
- call Asciify_Long
-
- mov ax,[bx].zModDate ; format file date
- call GetDate
-
- mov ax,[bx].zModTime ; format file time
- call GetTime
-
- mov ax,[bx].zCrc32 ; format crc in hex
- mov di,offset vcrc ;(just low word for now)
- call Cvh
-
- inc totmbrs ;bump total file count
-
- mov dx,offset vline ;display formatted info
- mov cx,VLINELEN
- call Pr_StdOut
- ret
-
- Show_Verbose endp
-
-
- ;v1.3 Formats, displays verbose totals
-
- Format_Totals proc near
-
- mov ax,totmbrs ;total members
- add ttotmbrs,ax ;accumulate
- mov di,offset vtmbrs-2 ;format total members
- call Asciify
-
- mov dx,totcmp[2] ;total compressed file size
- mov ax,totcmp
- add ttotcmp,ax ;accumulate total totals
- adc ttotcmp[2],dx
- mov di,offset vtlen ;format total compressed file size
- call Asciify_Long
-
- mov dx,totuncmp[2] ; total uncompressed file size
- mov ax,totuncmp
- add ttotuncmp,ax ;accumulate total totals
- adc ttotuncmp[2],dx
- mov di,offset vtsize ;format total uncompressed file size
- call Asciify_Long
-
- ; reduce the total size/length to word values
-
- mov si,totcmp ; get compressed file size
- mov ax,totcmp[2]
- mov cx,totuncmp ; uncompressed file size
- mov dx,totuncmp[2]
-
- FTDiv: or ax,ax ; big number?
- jz FT2 ; nope, can use it
- shr ax,1 ; yup, divide by two
- rcr si,1
- shr dx,1
- rcr cx,1
- jmp short FTDiv
-
- FT2:
- mov ax,si
- mov sign,' ' ;whata kludge
- cmp ax,cx ;compressed > uncompressed?
- jb FT3 ;yep
- sub ax,cx ;amount saved
- jmp short FT4
-
- FT3: sub ax,cx
- neg ax
- mov sign,'-'
-
- FT4: mul hundred ; to percentage
- add ax,50
- adc dx,0 ; round up percent
- or si,si ; empty file?
- jnz Ft5
- mov ax,100
- jmp short FT6
-
- FT5: div si
- FT6: mov di,offset vtsf-2 ;format stowage factor
- call Asciify ;AX
-
- mov al,sign
- mov vtsf,al
-
- mov di,offset totcmp ;starting at totcmp
- mov cx,TOTLEN/2 ;length of totals to clear (words)
- xor ax,ax ;handy 0
- rep stosw
-
- mov dx,offset vthdr ;prepare to display totals
- mov cx,VTHDRLEN ;msg length
- ret ;to display
-
- Format_Totals endp
-
-
- ; format the time (in AX)
-
- time record hour:5,min:6,sec:5 ;packed time
-
- GetTime proc near ;format the date
- mov di,offset vtime
- or ax,ax ;it is zero?
- jz GotTime
-
- push ax ;save date
- and ax,mask hour ;get hour part
- mov cl,hour ;bits to shift
- shr ax,cl
- call Cnvrt1
- stosw
- mov al,':'
- stosb
-
- GT3: pop ax ;get the time back
- and ax,mask min ;get min part
- mov cl,min ;bits to shift
- call Cnvrt
- stosw
- GotTime:ret
-
- GetTime endp
-
-
- Cnvrt2 proc near ;convert to ascii
-
- call Cnvrt
- cmp al,'0' ;suppress leading zero
- jne Cnvrtd
- mov al,' '
- ret
-
- Cnvrt: shr ax,cl
- Cnvrt1: aam ;make al into bcd
- or ax,'00' ; and to ascii
- xchg al,ah
- Cnvrtd: ret
- Cnvrt2 endp
-
- page
-
- ; format the date (in AX)
-
- date record yr:7,mo:4,dy:5 ;packed date
-
- GetDate proc near ;format the date
- or ax,ax ;is it zero?
- jz GotDate
-
- push bx ;preserve BX (buff ptr)
-
- push ax ;save date
- and ax,mask yr ;get year part
- mov cl,yr ;bits to shift
- call Cnvrt
- mov di,offset vyear
- or al,'8' ;adjust for base year
- stosw
-
- pop bx ;get the date back
- push bx ;save it
- and bx,mask mo ;get month part
- mov cl,mo ;bits to shift
- shr bx,cl
- add bx,bx ; form month table index
- add bx,bx
- lea si,word ptr months-4[bx]
- mov cx,word ptr 3
- mov di,offset vmonth
- rep movsb
-
- pop ax ;get the date back
- and ax,mask dy ;get day part
- mov cl,dy ;bits to shift
- call Cnvrt
- mov di,offset vdate
- stosw
-
- pop bx ;restore buff ptr
- GotDate:ret
-
- GetDate endp
-
-
- ;v1.3 A severely hacked single/double precision number conversion function.
- ; Originally from JMODEM, but severely hacked by Toad Hall.
- ; ES:DI -> string
- ; Destroys everything almost.
-
- ;Enter here if integer in AX
- Asciify proc near
-
- push bx ;save buff ptr
-
- xor dx,dx ; clear fake long.hi
- mov si,ax ;move integer into SI
- xor ah,ah ;clear msb (flag)
- jmp short Ascii_Ax ;jump into the code
-
- ;Enter here if long integer in DX:AX.
- Asciify_Long:
-
- push bx ;save buff ptr
-
- mov si,ax ;move long.lo into SI
- xor ah,ah ;clear msb (flag)
-
- Comment ~
- Taking out the extremely high numbers to reduce column width.
-
- MOV CX,3B9AH ; Get billions
- MOV BX,0CA00H
- CALL Subtr ; Subtract them out
-
- MOV CX,05F5H ; Get hundred-millions
- MOV BX,0E100H
- CALL Subtr ; Subtract them out
- Comment ends ~
-
- and dx,4FFH ;seems likely
- MOV CX,word ptr 0098H ; Get ten-millions
- MOV BX,9680H
- CALL Subtr ; Subtract them out
-
- MOV CX,word ptr 000FH ; Get millions
- MOV BX,4240H
- CALL Subtr ; Subtract them out
-
- MOV CX,word ptr 1 ; Get hundred-thousands
- MOV BX,86A0H
- CALL Subtr ; Subtract them out
-
- Ascii_Ax:
- xor cx,cx ; Get ten-thousands
- MOV BX,2710H
- CALL Subtr ; Subtract them out
- MOV BX,03E8H
- CALL Subtr ; Subtract them out
-
- MOV BX,word ptr 0064H
- CALL Subtr ; Subtract them out
- MOV BX,word ptr 10
- CALL Subtr ; Subtract them out
- mov ax,si ;residual in SI
- add AL,'0' ; Add bias to residual
- stosb ; Put in the string
-
- pop bx ;restore buff ptr
- RET
-
- ;Common subroutine for Asciify
-
- Subtr: mov al,'0'-1
-
- Subtr1: INC al ; Bump the digit character
- SUB si,BX ; Dword subtraction
- SBB DX,CX
- JNB Subtr1 ; Continue until a carry
-
- ADD si,BX ; One too many, add back
- ADC DX,CX ; and the remainder
-
- cmp al,'0'
- jnz Subtr2 ;nope, turn off leading flag, stuff
- or ah,ah ;no more leading spaces?
- jnz Sub_Stuff ;right, stuff the '0'
- mov al,' ' ;make it neat with leading spaces
- Sub_Stuff:
- stosb ;stuff the char
- RET
-
- Subtr2: inc ah ;turn off leading space flag
- stosb
- ret
-
- Asciify ENDP
-
-
- ;v1.3 Convert 16-bit binary word in AX
- ; to hex ASCII string at ES:DI
- ; (Protect BX, directory array pointer)
-
- hexchar db '0123456789ABCDEF'
-
- Cvh proc near
-
- push bx ;save buff ptr
-
- mov si,offset hexchar ;for faster access
- mov dx,ax ; save 16-bits
-
- mov bl,dh ; third nibble
- xor bh,bh ;clear msb
- mov cx,0F04H ;CL=4 for shifting,
- ;CH=0FH for masking
- shr bl,cl
- mov al,[si][bx] ;snarf hex char
- stosb
-
- mov bl,dh ; last nibble
- and bl,ch ;0fh
- mov al,[si][bx] ;snarf hex char
- stosb
-
- mov bl,dl ; first nibble
- shr bl,cl ; isolate (CL still 4)
- mov al,[si][bx] ;snarf hex char
- stosb
-
- mov bl,dl ; second nibble
- and bl,ch ;0fh ; isolate
- mov al,[si][bx] ;snarf hex char
- stosb
-
- pop bx ;restore buff ptr
- ret
-
- Cvh endp
-
-
- ;SUBROUTINE
-
- Pr_CrLf proc near
- mov dx,offset crlf
- mov cx,CRLFLEN ;fall through to ...
-
- Pr_CrLf endp
-
- Pr_StdOut proc near
-
- push bx ;preserve bx
- mov bx,STDOUT
- mov ah,40H ;write
- int 21H
- pop bx
- ret
-
- Pr_StdOut endp
-
-
- ;v1.3 print null-terminated (AsciiZ) string like int 21h function 9
- ; Enter with DS:DX -> AsciiZ string
- ; destroys AX
- ; On success, return:
- ; CF clear
- ; AL = 0
- ; On failure (StdOut write fail), return:
- ; CF set
- ; AL = error
-
- PrintS proc near
-
- mov cx,0FFFFH ;max scan v1.3
- xor al,al ;handy 0 v1.3
- mov di,dx ;string start v1.3
- repne scasb ;find the terminator v1.3
- inc cx ;adjust v1.3
- not cx ;CX=length v1.3
-
- call Pr_StdOut ;display to StdOut
-
- ret
-
- PrintS endp
-
-
- ;Reinit our nonverbose formatted display line
-
- Refresh_LineBuff proc near
-
- mov si,offset blankline ;formatted display line
- mov ax,offset LINEBUFF ;dynamic data area
- mov di,ax ;move to ...
- mov cx,LINELEN ;length
- rep movsb
- mov di,ax ;ES:DI -> formatted line start
- ret
-
- Refresh_LineBuff endp
-
-
- ;v1.2 Parses cmdline for target files.
- ; If failure:
- ; Returns CF set,
- ; AL = ERRORLEVEL,
- ; DX -> error msg
- ;v1.3 Adding command line switch ('-v') parsing.
- ;v1.3b And fixing the bug.
-
- Parse_CmdLine proc near
-
- call _Args ;parse cmdline
- ;returns AX = argc
- or ax,ax ;any argc?
- jnz Got_Parm ;yep
-
- Cmd_Err:
- mov dx,offset usage ;intro, usage
- mov cx,USAGELEN ;total length
- mov al,1 ;errorlevel 1
- stc ;CF set
- ret ;for a jmp to Msg_Term
-
- Got_Parm:
- mov cx,ax ;argc
-
- ;See if any of the argv's are our '-v' verbose switch.
- ;If so, turn switch on, clear that argv.
-
- cmp cx,1 ;just 1 arg?
- jz Chk_ZipName ;yep, can't be any switches
-
- mov bx,offset argv[2] ;start with ^argv(1)
-
- Chk_VSwitch:
- mov si,[bx] ;argv^(1)
- cmp word ptr [si],'V-' ;'-V' backwards
- jnz Chk_VRelup ;nope
- cmp byte ptr 2[si],0 ;Just the '-v'?
- jnz Chk_VRelup ;nope, must be a name
- not verbose ;got '-v', verbose on
- mov byte ptr [si],0 ;clear this argv
- cmp cx,argc ;first argc?
- jnz Chk_V_NoShift ;nope
- inc argc ; .. sigh .. readjust
- call _Shift ;yep, move other args down one
- ;(will decr argc again)
- Chk_V_NoShift:
- dec argc ;final decr to eliminate it
- jmp short Chk_ZipName ;done
-
- Chk_VRelup:
- add bx,2 ;next argv^
- loop Chk_VSwitch ;check all args
-
- ;If argv(1) was the '-v' switch,
- ;that argv has been cleared via the _Shift call.
- ;The target zip file name HAS to be argv(1)!
-
- Chk_ZipName:
-
- mov cx,argc ;argc arg counter
- jcxz Cmd_Err ;he only had a switch!
-
- mov bx,offset argv[2] ;^argv(1)
- mov si,[bx] ;argv^(argc)
- call Parse_MoveZipName ;handle the zip name
- ; mov byte ptr [si],0 ;clear this arg
- call _Shift ;move argv's down one
-
- ;Check for member testing (2d or 3d argv).
- ;We make the call even if argc = 0 (to clear a buffer)
-
- Chk_MbrName:
- call Parse_MoveMbrName ;handle the member name
-
- Parse_Done:
- clc
- ret
-
- Parse_CmdLine endp
-
- ;v1.3b Cmdline parsing subroutine
- ; Moves argv into our targetfile buffer,
- ; picks up a pointer to past the paths (if any)
- ; SI -> argv
-
- Parse_MoveZipName proc near
-
- push si ;save SI
-
- mov bx,offset ziptarget ;full zip target filename
-
- mov di,bx
- mov cx,64 ;clear ziptarget
- xor ax,ax
- rep stosw
-
- mov di,bx ;DI -> ziptarget
-
- Move_ZipName:
- lodsb ;snarf cmdline char
- or al,al ;AsciiZ terminator?
- jz Parse_Zip_Type ;yep
- stosb ;stuff
- jmp Move_ZipName
-
-
- Parse_Zip_Type:
-
- ;DI -> last ziptarget's real char +1
-
- mov dx,di ;end, last char +1
- sub dx,bx ;end - start = length
-
- mov di,bx ;back to start
- mov cx,dx ;counter for a scan
- mov al,'.'
- repne scasb ;find a .TYP separator
-
- ;DI -> char after '.' or actual filename end
- jnz No_Type
- dec di ;back up to the '.'
- No_Type:
- mov si,offset ziptyp ;assume need full '.ZIP'
- mov cx,4 ;4 chars
- rep movsb ;copy .ZIP in
-
- mov dx,di ;end
- sub dx,bx ;end - start = length
-
- dec di ;adjust from last movsb
- std ;backwards
-
- mov si,di ;SI -> ziptarget last char
-
- ;BX = ziptarget start
- ;SI -> ziptarget lastchar
- ;DX = ziptarget length
- ;DI -> ziptarget lastchar
-
- ;Now find any path separators in ziptarget
-
- mov cx,dx ;scan length
- mov al,'\' ;subdir dividers
- repne scasb ;scan till we hit one
- jz Zip_GotPath ;DI -> char before the '\'
-
- mov di,si ;back to last char
- mov cx,dx ;scan length
- mov al,':' ;how about just drive?
- repne scasb
- jnz Zip_NoPath ;nope, DI -> ziptarget-1
- ;skip the extra inc
- Zip_GotPath:
- inc di ;bump to '\' or ':'
- Zip_NoPath:
- inc di ;and past it to filename's char
- cld ;forward again
- mov znameptr,di ;points to start of
- ;true filename (beyond path)
- ;for later appending Find Next
- ;filenames to path
- pop si ;restore
- ret
-
- Parse_MoveZipName endp
-
- ;v1.3b Cmdline parsing subroutine
- ; Has DOS parse the member name (could be wildcards).
- ; Moves that parsed name into runtime buffer.
- ; Enters with SI -> AsciiZ member name.
-
- Parse_MoveMbrName proc near
-
- mov di,offset pname1
- mov cx,6 ;12 bytes long
- mov ax,2020H
- rep stosw ;clear with spaces
-
- mov cx,argc ;argc counter
- jcxz Parse_MbrDone ;all done, no member
-
- mov bx,offset argv[2] ;it's now ^argv(2)
- mov si,[bx] ;argv^(argc)
-
- mov di,offset fcb3
- mov ax,2900H + 00001100b ;parse filename
- ;(no leading spaces,
- ; don't set drive spec,
- ; change only if valid)
- int 21H
- cmp al,0FFH ;failed?
- jz Parse_MbrDone ;yep
-
- mov si,di ;0 preceding parsed name
- inc si ;bump past 0
- mov di,offset pname1 ;dynamic variable space
- mov cx,6 ;11 filename chars + AsciiZ 0
- rep movsw
-
- Parse_MbrDone:
- ret
-
- Parse_MoveMbrName endp
-
- ;---- args.asm ----------------------------------------------------------
- ;from KEGELUNX.ARC Unix-like utils.
- ;
- ; Args parses the command line into a unix-style parameter array.
- ; CALL _ARGS to have it parse the cmdline.
- ; Argc and Argv are just as in C; argc = # of params on cmd line,
- ; argv is an array of pointers to strings (null terminated, of course).
- ; Because MS-DOS doesn't pass us the name used to invoke the program,
- ; argv[0] always points to a null string.
- ; _Shift updates argc.
- ;
- ;--------------------------------------------------------------------------
-
- ; Maximum number of parameters
- MAXPARMS equ 4
-
- _Args proc near
- ; initialize
- cld ; clear decrement mode
- mov bx, 2 ; argc = 0 (will sub 2 from bx at end)
- mov argv[0], offset null ; prog name unknown; set to null.
- mov si,offset PARAMS ; i = 0
- mov cl,nchar ; cx = # of chars in command line
- xor ch,ch
- jcxz Args_Done ; no arg chars -> we're done.
-
- mov di,offset argbuff ;big arg buffer
-
- ; Move arguments out of default DTA.
- push cx
- push di
- rep movsb
- pop si
- pop cx
-
- ; Big loop- find arguments...
- mov ah,20H ;handy space
- ParmL:
- ; Little loop #1: strip leading blanks from argument.
- ; while (i<NCHAR && params[i] = ' ') do i++;
- StripL: lodsb ; al = [si++]
- cmp al,ah ; space?
- loopz StripL ; if so, keep skipping.
- jne Args_GotOne ; If we found a nonblank, skip zero test.
- jcxz Args_Done ; found no unblank chars -> we're done.
-
- Args_GotOne:
- dec si ; bump SI back to start of nonblank.
- inc cx
- mov argv[bx],si ; save pointer to this string
-
- ; Little loop #2: skip nonblank chars.
- ; while (i<NCHAR && params[i] <> ' ') do i++;
- SkipL: lodsb
- cmp al,ah
- loopnz SkipL
- jz Oky
- ; Last char of line was not blank.
- inc si ; make next statement put null AFTER arg.
- Oky:
- mov byte ptr [si][-1], 0 ; put null at end of arg
- add bx,2 ; argc++;
-
- jcxz Args_Done ; if we ran off end of cmdline, no more args.
-
- cmp bx, MAXPARMS*2
- jb ParmL ; loop if argc < MAXPARMS.
-
- Args_Done: ; All done finding parms; now share argc with caller.
- mov ax,bx
- sub ax, 2
- shr ax, 1
- mov argc,ax ;save argc
- or ax,ax ;no args at all? v1.3c
- jz Args_X ;yep, leave now v1.3c
-
- ;While we're here, let's uppercase all the args
-
- mov cx,ax ;argc loop counter
- mov dl,20H ;handy constant for uppercasing
- mov ah,'a' ;and for testing
- mov bx,offset argv[2] ;^argv(1)
-
- Args_UpLoop:
- mov si,[bx] ;argv^(argc)
- dec si ;prep for upcoming...
- Argv_UpLoop:
- inc si
- mov al,[si] ;snarf char
- or al,al ;argv^(argc) end?
- jz Args_Relup ;yep, bump argc
- cmp al,ah ;'a' ;lowercase?
- jb Argv_UpLoop ;nope
- sub [si],dl ;uppercase
- jmp Argv_UpLoop ;next char
-
- Args_Relup:
- add bx,2 ;next argv^
- loop Args_UpLoop
-
- mov ax,argc ;return argc
- Args_X:
- ret
-
- _Args endp
-
- ;---- _Shift: --------------------------------------------
- ; Shifts %2 to %1, %3 to %2, etc. Leaves %0 alone.
- ; Works by shuffling argv[*].
-
- _Shift proc near
- cld
- mov si, offset argv[4]
- mov di, offset argv[2]
- mov cx, MAXPARMS
- rep movsw
- dec argc
- ret
- _Shift endp
-
-
- ;---- parameter count, array ----------------
- ; Pointers to up to MAXPARMS parameter strings are held here.
-
- null dw 0 ; the null string
- argc dw ?
- argv dw MAXPARMS dup (null)
-
-
- ;Dynamic variables start here.
- ;Not REAL big .. we could calculate them and release unneeded memory ..
- ;but who needs it? This ain't TSR, and the normal 64Kb required for
- ;a .COM program shouldn't stress anyone's system capacity.
-
- dta1BA equ $ ;alternate DTA
- ziptarget equ dta1BA + 42 ;up to 128 bytes
- pname1 equ ziptarget + 128 ;11-byte FCB filename + 0
- fcb3 equ pname1 + 14 ;full 44-byte FCB
-
- Comment ~ Looks like:
- +filename.typ 000K / 000K +filename.typ 000K / 000K +filename.typ 000K / 000K
- Comment ends ~
- argbuff equ fcb3 + 44 ;cmdline parsing buff v1.3b
- linebuff equ argbuff ;82 chars long
- dirbuff equ linebuff + 82 ;ENDOFS bytes long
-
-
- CSEG ends
- end Zdir
-