Fileinfo

18 views
Skip to first unread message

Kerr-Mudd,John

unread,
Feb 13, 2019, 11:27:56 AM2/13/19
to
Here's an old program from the 90's? I've recently rewritten for size;
Original masm code (nice and modular!) Public Domain, if anyone wants it!



; get file info
.radix 16

code segment

parm_dlm equ '/'
date_dlm equ '-'
time_dlm equ ':'
readonly equ 1
hidden equ 2
system equ 4
volume_label equ 8
subdir equ 10h
archive equ 20h
org 100
include stdequ.inc
include stdmcr.inc
include fileio.inc
assume cs:code,ds:code

mov dx,offset Dta
dos set_dta

call get_psp
jnc got_a_psp
; no parms - default to *.*, nopts
mov dx,offset all
mov cx,0
mov di,82h
mov word ptr [parm_ptr],di
mov word ptr [parm_lth],cx
jmp do_first
; got something - is it just opts?
got_a_psp:

; if 1st word doesnt contain a parm_dlm, then call it a filespec
; call test_for_opts

; test_for_opts proc near
; cy set on exit if delim speced
push cx
push di
mov di,si
mov cx,ax ; lth 1st str
mov al,parm_dlm
repnz scasb
clc
jcxz noslash1
stc
; get char after / - is it a ?
mov al,byte ptr [si+1]
noslash1:
pop di
pop cx
; ret
; test_for_opts endp
; allow help
pushf
cmp al,'?'
je err
popf
jnc file_ok


; no file speced - so make it general
add cx,di ;
sub cx,si ; orig plth ?
mov di,si ; pt back to opts list
; (dont care about di)
; got str
mov word ptr [parm_ptr],di
mov word ptr [parm_lth],cx
mov dx,offset all
jmp do_first
file_ok:
mov word ptr [di],0
inc di
mov word ptr [parm_ptr],di
mov word ptr [parm_lth],cx
mov dx,si ; pt to start fn
do_first:
dos fget_first
jc err ; no files match

next_file:
call print_fn
mov cx,word ptr [parm_lth]
mov si,word ptr [parm_ptr]
call print_info
prtcrlf
dos fget_next
jnc next_file
; - tot files, size?
; prtstr done_all

jmp ext
err:
prtstr usaje
ext:
exitrc 0

print_fn proc near
mov dx,offset file_name ; filename

mov si,dx
mov cx,8d ; fn lth
lodsb
p_n1:
prtal
lodsb
cmp al,'.'
je gotdot1
or al,al
loopnz p_n1
prtbl
; end fn - no dot
add cx,5 ; fill print for extn
call remaining_blanks
ret
gotdot1:
call remaining_blanks
mov cx,5
lodsb ; skip '.'
call prt_ascz
call remaining_blanks

ret

print_fn endp

prt_ascz proc near
prtal
lodsb
or al,al ; ascz?
loopnz prt_ascz
ret
prt_ascz endp

remaining_blanks proc near
; fill remainder with spaces
mov al,blank
p_n2:
prtal
loop p_n2
ret

remaining_blanks endp

print_info proc near
jcxz done_opts

parse_next_opt:
lodsb
push cx
; what opts?
; - get opt letter
or al,20

cmp al,'a'
jne nota
call prt_attr
call pbl
jmp short nxto
nota:
cmp al,'d'
jne notd
call prt_date
call pbl
jmp short nxto
notd:
cmp al,'s'
jne nots
call prt_size
call pbl
jmp short nxto
nots:
cmp al,'t'
jne nott
call prt_time
call pbl
jmp short nxto
nott:
; not a valid option
; - but dont worry
nxto:
pop cx
loop parse_next_opt

done_opts:
ret
print_info endp


prt_size proc near

mov ax,word ptr [file_size] ; low size
mov dx,word ptr [file_size+2] ; high size
mov cx,10d
mov bx,8 ; num chrs to prt & bh=0
call rec_prt2
ret

prt_size endp

rec_prt2 proc near
DIV CX ; div by 10
; any flags set?
PUSH DX ; add num to stack
inc bh ; keep a count of stack depth
XOR DX,DX ; clean for next (not nec after 1st)

OR AX,AX ; push last dx as well
JZ r_skipit2
CALL rec_prt2 ; recurse!
; done a stack layer
r_skipit2:
; now at bottom of stack
; stck now set - print lding blanks, then pop stack
prtld_bl2:
cmp bh,bl ;
jge prtnumeral
; lding blank
call pbl
inc bh
jmp prtld_bl2

prtnumeral:
POP DX ; take from stack and prt
MOV AH,02 ; prt char
ADD DL,30h ; cvrt to disp num
INT 21h
mov Ah,0
RET
rec_prt2 endp

pbl proc near
prtbl
ret
pbl endp

prttab proc near
push dx
mov ah,02
mov dl,tab
int 21
pop dx
ret
prttab endp

prt_attr proc near

test byte ptr [file_attr],system
jz not_sys
prtstr sys
not_sys:

test byte ptr [file_attr],readonly
jz not_readonly
prtstr ro
not_readonly:

test byte ptr [file_attr],hidden
jz not_hid
prtstr hid
not_hid:

test byte ptr [file_attr],archive
jz not_archive
prtstr arch
not_archive:

test byte ptr [file_attr],volume_label
jz not_volume
prtstr vol
not_volume:

test byte ptr [file_attr],subdir
jz not_dir
prtstr dir
not_dir:

ret

prt_attr endp

prt_date proc near

call get_day
call prt_2_dec
mov al,date_dlm
call p_char
call get_mth
call prt_2_dec
mov al,date_dlm
call p_char
call get_yr
call prt_2_dec
ret
prt_date endp

get_yr proc near
mov ax,word ptr [file_date]
mov cl,9
shr ax,cl
add ax,80d
CMP ax,100d
jb this_cent
sub ax,100d
this_cent:
ret
get_yr endp

get_mth proc near
mov ax,word ptr [file_date]
mov cl,5
shr ax,cl
and ax,00000000000001111b
ret
get_mth endp

get_day proc near
mov ax,word ptr [file_date]
and ax,00000000000011111b
ret
get_day endp

prt_time proc near
call get_hr
call prt_2_dec
mov al,time_dlm
call p_char
call get_min
call prt_2_dec
mov al,time_dlm
call p_char
call get_sec
call prt_2_dec
ret
prt_time endp

get_hr proc near
mov ax,word ptr [file_time]
mov cl,11d
shr ax,cl
ret
get_hr endp

get_min proc near
mov ax,word ptr [file_time]
mov cl,5
shr ax,cl
and ax,00000000000111111b
ret
get_min endp

get_sec proc near
mov ax,word ptr [file_time]
and ax,00000000000011111b
ret
get_sec endp


include useful.rtn
include words.rtn

DTA equ $
fill db 21d dup(?)
file_attr db ?

; would need to mod code to pick up dir entries, & not show space
file_time dw ?
file_date dw ?
file_size dd ?
file_name db 13d dup (?) ; inc ascz

parm_ptr dw ?
parm_lth dw ?

usaje db 'File not found - Usage is:'
db '"QFILE filespec [',parm_dlm,'options]"',cr,lf
db 'options:',cr,lf
db tab,'s - size in bytes',cr,lf
db tab,'d - date',cr,lf
db tab,'t - date & time',cr,lf
db tab,'a - attribs'
crlf db cr,lf
db eos

ro db 'Readonly ',eos
arch db 'Archive ',eos
vol db 'Volume ',eos
dir db 'Directory ',eos
sys db 'System ',eos
hid db 'Hidden ',eos


all db '*.*',0

code ends


end






--
Bah, and indeed, Humbug.

Kerr-Mudd,John

unread,
Feb 13, 2019, 11:31:34 AM2/13/19
to
On Wed, 13 Feb 2019 16:27:55 GMT, "Kerr-Mudd,John"
<nots...@invalid.org> wrote:

> Here's an old program from the 90's? I've recently rewritten for size;
> Original masm code (nice and modular!) Public Domain, if anyone wants

[old code snipped]; com file 872 bytes

and here's the improved 445 byte version:

comments welcome!

(Note followup set to just clax)

; get file info [445] works!

; added commas to size
;; revert to parsing opts for each file
;; re-added 'file not found' msg
; @@@extend to give dir list & allow DC cmds
;cpu 286
cpu 8086
parm_dlm equ '/'
date_dlm equ '-'
time_dlm equ ':'
PSP equ 0x0080
org 0x100
; stdequ
cr equ 0x0D
lf equ 0x0A
eos equ '$'
blank equ 0x20
tab equ 0x09
;DOS fns:
set_dta equ 0x1A
prtstr equ 0x09
exitrc equ 0x4C
fget_first equ 0x4E
fget_next equ 0x4F
%macro dos 1
mov ah,%1
int 0x21
%endm
;------------------------------------------------
Start:
mov dx,DTA
dos set_dta ; set area for info
mov bx,allfiles ; posit no filespec
mov si,asczb ; posit no opts
;; check parms
xor cx,cx
mov di,PSP
mov cl,byte [di]
jcxz just_do_it ; default to just listing all
inc di ; avoid initial space
inc cx ; include cr
add_fn:
mov dx,bx ; pt dx at fn
find_again:
;; mkascz, rtn bx->asczstr,[di]=0
mov al,blank
repz scasb ; skip leading spaces
jcxz just_do_it ; end ofpsp
dec di ; 1st nonblank
inc cx
mov bx,di
repnz scasb ; find end
;; found or EoI
mov byte [di-1],0 ; end word with ascz

cmp byte [bx],parm_dlm ; opts?
jne add_fn
at_dlm: ;; any parms?
mov si,bx ; pt si at opts
inc si ; past /
cmp byte [si],'?' ; was it /?
jne find_again
; je usage
;usage:
mov dx,usaje
msgexit:
dos prtstr
exitwrc:
dos exitrc ; EOprog


just_do_it:
dos fget_first
mov dx,badfn
jc msgexit ; no files match/error
next_file:
push si ; keep si at opts
mov di,OBuff
push di ; dx for print later
push si ; keep si at opts
call print_fn ; must call to allow fallthru
;print_info:

next_opt: ; jmps to prt_etc come back here
mov al,blank ; space between entries
stosb
gn_opt:
pop si
lodsb ; opts
and al,0xFF-0x20 ; ucase
jz end_opts ; space or 0 ends
push si ; all rtns to next_opt
cmp al,'D'
je prt_date
cmp al,'T'
je prt_time
cmp al,'S'
je prt_size
cmp al,'A' ; lookup table costs more
; je prt_attr
jne gn_opt ; nonvalid

prt_attr: ; [18] +2
mov cl,lattrs
mov si,attrltrs
; mov ah,byte [file_attr] ; [4]
mov ax,word [file_attr-1] ; [3]
next_bit:
lodsb
shr ah,1
jc attr_on
mov al,blank
attr_on:
stosb
loop next_bit
jmp next_opt


end_opts: ; all opts dealt with
mov si,endline
movsw ; crlf
movsb ; eos
pop dx ; mov dx,OBuff
dos prtstr ; Print line

pop si ; opts
dos fget_next
jnc next_file
; - tot files, size? no regs left
; prtstr done_all
; jmp exitwrc
ret ; EOprog

prt_date:
mov si,date_parms
mov bl,date_dlm
mov ax,word [file_date]
prt_cent:
push ax ; save raw date/time
;; y2k century special code (max 2099)
mov cl,9
shr ax,cl ; shift
mov dx,'20' ; default to 21st cent
sub al,20d
jnc is21th_cent
mov dx,'19'
add al,100d ; 1980<=ccyy<2000
is21th_cent:
mov word [di],dx
scasw ; inc di past century
no_cent:
call prt_2_dec
jmp prt_rest

prt_time:
mov si,time_parms
mov bl,time_dlm
mov ax,word [file_time]
push ax ; save raw date/time
call prt_nn
; fallthru
prt_rest:
pop ax ; restore base date/time num
call prt_dlm_nn_dlm_nn
jmp next_opt

prt_size:

;putnum8: ;[x28=40] big prt +ve bp:ax 4G max; with commas
mov cl,13 ; 4,000,000,000 chrs max
call nblanks ; [3] ; moves di to end

mov ax,word [file_size] ; low size [3]
mov bp,word [file_size+2] ; high size [4]

xor bx,bx ; -ve count
prt_num8:
mov cl,0x0A ; base 10
adddig8:
dec bx ; next prt posn
push bx
and bl,3 ; F4,F8,FC,[00]
pop bx
jnz nocomma8 ; every 4
mov byte [di+bx],',' ; comma every 4 decs
dec bx
nocomma8:

xor dx,dx
xchg ax,bp ; high part
div cx
xchg ax,bp ; store/high restored low
div cx ; using dx as rmdr from 1st
or dl,'0'
mov byte [di+bx],dl
or ax,ax
jnz adddig8

jmp next_opt


;;; called rtns ------------------------------------
print_fn:
mov si,file_name
mov cl,8 ; fnlth (inc .)
call MovDotZstrThenPad ; fn
mov cl,3 ; extn
; fallthru for extn
MovDotZstrThenPad:
lodsb ; [11]
prt2dot:
stosb ; at least 1 char
lodsb
cmp al,'.' ; until '.'
je endmov
or al,al ; or ascz
loopnz prt2dot ; cx chrs max
endmov: ; fallthru to pad rmdr
nblanks:
mov al,blank
repnz stosb
ret

prt_dlm_nn_dlm_nn:
push ax ; save raw date/time
call prt_dlm_nn
pop ax
; fallthru for 2nd @nn
prt_dlm_nn:
mov byte [di],bl ; prt dlm
inc di
; fallthru for nn
prt_nn:
; mov cx,word [si] & si++ [4]
xchg ax,cx ; store raw d/t
lodsw
xchg ax,cx ; load s&m [3]
shr ax,cl ; shift
and al,ch ; & mask
xor cx,cx ; need ch=0 later?
; fallthru for prt
prt_2_dec: ; <=99 in al [9]
;; reuse prt from size?? [8]
; xor bp,bp
; mov cl,2
; inline prt_num ;
; ret
;; but must add these to prt_size:
; call prt_num ; noret fail!
aam 10 ; split digits
xchg ah,al
or ax,0x3030
stosw ; nn
ret

;data -----------------------------------------

date_parms: ; cent/yr in code
; db 9 ; dys ;15-09 Year
;;(0 = 1980, 119 = 2099 DOS/Windows)
; db 001111111b ; dym 128
db 5 ; dms ;08-05 Month (1–12)
db 000001111b ; dmm 16
db 0 ; dds ;04-00 Day (1–31)
db 000011111b ; ddm 32

time_parms:
db 11 ; ths ;15-11 Hours (0-23)
db 000011111b ; thm 32
db 5 ; tms ;10-05 Minutes (0-59)
db 000111111b ; tmm 64
db 0 ; tss ;04-00 Seconds/2 (0-29)
db 000011111b ; tsm 32

allfiles db '*.*' ; asczb must be next
asczb db 0
OBuff equ $ ; make sure it's long enough to avoid data
badfn db 'File not found: - '
usaje db 'Usage is:'
db '"QFILE filespec [',parm_dlm,'{D|T|S|A}]"',cr,lf ;,lf
db tab,'{D}ate CCYY',date_dlm,'MM',date_dlm,'DD',cr,lf
db tab,'{T}ime HH',time_dlm,'MM',time_dlm,'SS',cr,lf
db tab,'{S}ize in bytes',cr,lf
db tab,'{A}ttr '
;; data & part of help info
attrltrs db 'RHSVDA'
lattrs equ $-attrltrs
endline db cr,lf
db eos

;SECTION DATA
DTA equ $
file_attr equ $+21
file_time equ $+22
file_date equ $+24
file_size equ $+26
file_name equ $+30
Reply all
Reply to author
Forward
0 new messages