home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
ftp.shrubbery.net
/
2015-02-07.ftp.shrubbery.net.tar
/
ftp.shrubbery.net
/
pub
/
pc
/
unix
/
unx.arc
/
LS.ASM
< prev
next >
Wrap
Assembly Source File
|
1986-05-07
|
24KB
|
1,244 lines
page 66,132
page
;---- ls.com ---------------------------------------------------------------
; Usage: ls {-options} {name}
; Lists files on given directory.
; Default is current directory.
; Options: alsR1
; a- show all system & hidden files, too
; l- long format- show size, protection, time of last modification.
; s- show size.
; R- recursive- show contents of all subdirectories, too
; 1- one file per line (default is multicolumnar output, unless -l or -s).
; DRK 24 July 84
; CCW March 1985 - changed over to sprintf, improved -l
; DRK 7 April 1985 - fixed tens digit in minutes in -l
; DRK 7 May 1986 - ripped out stupid _ code, added .. kludge for DOS 3.x
;------------------------------------------------------------------------------
; main(argc, argv);
; int argc;
; char *argv;
; {
; char fname[128];
;
; /* The main program prepares the argument for passing to the
; recursive CHECKFILE procelsre.
; This is the same preparation needed in the program LS. */
;
; sea_atr = directory; /* includes normal files */
; if (opt_a)
; sea_atr = hidden + directory;
;
; if (argv > 1) error;
;
; fname[0] = '/0';
; if (argc > 0) strcpy(fname, argv[2]);
;
; /* No argument, or default directory? */
; if (fname[0] == '\0' || (fname[0] == '.' && fname[1] == '\0'))
; /* leave a drive specifier for next if statement */
; fname[0] = 'A' + current_drive;
; fname[1] = ':';
; fname[2] = '\0';
; }
;
; /* Drive specifier only? If so, get default directory for that drive */
; if (fname[1] == ':' && fname[2] == '\0') {
; fname[2] = '\';
; getpath(fname+3, toupper(fname[0])-'A'+1 );
; if (fname[3] != 0) /* root directory */
; strappend(fname, "\");
; }
;
; /* Is it wildcarded? If so, it cannot be a directory. */
; for (i=0; i<strlen(fname); i++)
; wild = (fname[i] in ['?', '*']);
;
; /* Is it a directory (does it end with a slash) ? */
; if (!wild && !(fname[len-1] in ['/', '\'])) {
; type = chmod(0, fname);
; if (type & directory) {
; strappend(fname, "\");
; }
;
; if (fname[len-1] in ['/', '\'])
; strappend(fname, "*.*");
;
; depth = 0;
; eval(checkspec);
; }
;
extrn _args:near,_shift:near,argc:word,argv:word
extrn new:near,sprintf:near
extrn rindex:near, strcmp:near
stdout equ 1
stderr equ 2
fnameo equ 158 ; offset of filename from CS.
fattrib equ 149 ; offset of file attribute byte from CS.
dos macro fn
mov ah, fn
int 21h
endm
move macro w2, w1
mov ax, w1
mov w2, ax
endm
movb macro b2, b1
mov al, b1
mov b2, al
endm
code segment public 'CODE'
assume cs:code,ds:code
org 100h
ls proc near
jmp main
db 27
db '[2J'
db 'ls; 1985 Dan Kegel & Chris Worell, Pasadena, CA', 13, 10
db 'Take this, brother, may it serve you well.', 13, 10
umsg: db 'Usage: ls {-alrstR1} name', 13, 10
umsgl equ $-umsg
db 26 ; eof for random prints
dotdot db "..",0 ; | for .. kludge
opt_a db ?
opt_l db ?
opt_r db ?
opt_s db ?
opt_t db ?
opt_RR db ?
opt_1 db ?
nopts equ 7
sea_atr dw ? ; attributes to use when searching.
colcount db ?
depth dw ?
fname dw ?
wild db ?
number: db 10 dup (?) ; where we put string of dirsize
; Directory attribute field bits
A_BACKNEEDED equ 20h ; set if written since last backup
A_DIRECTORY equ 10h
A_VOLUME equ 8h
A_HIDDEN equ 4h
A_SYSTEM equ 2h
A_READONLY equ 1h
sattribs: db 'dhsrwx',0
nattribs equ 6
scontrol: db ' %8ld ',0
fcontrol: db '%-14s',0
lcontrol: db '%s %8ld %s %2d',0
ycontrol: db ' %4d ',0
tcontrol: db ' %2d:%02d ',0
pbuffer: db 90 dup (?)
months: db 'Jan',0,'Feb',0,'Mar',0,'Apr',0,'May',0,'Jun',0
db 'Jul',0,'Aug',0,'Sep',0,'Oct',0,'Nov',0,'Dec',0
db 'Time To Get A New Calendar', 0
; Hee,hee,heeeeheee! Are we Unix yet?
EXT_BAT: db 'bat',0
EXT_COM: db 'com',0
EXT_EXE: db 'exe',0
pe_dp db ? ; last level- if it changes, do a CRLF
main:
call _args ; Get arguments.
cld
mov al, 0 ; reset all switches
mov di, offset opt_a
mov cx, nopts
rep stosb
bigalp: cmp argc, 1
jb no_opts
mov si, argv[2]
lodsb
cmp al, '-'
jnz no_opts
; He gave some options; set the needed flags.
; There are so many options for ls that I'll just ignore
; unimplemented options.
aloop: lodsb
or al, al
jz adone
cmp al, 'a'
jnz AL1
mov opt_a, al
jmp short aloop
AL1: cmp al, 'l'
jnz AL2
mov opt_l, al ; some options force -1
mov opt_1, al
jmp short aloop
AL2: cmp al, 's'
jnz AL3
mov opt_s, al
jmp short aloop
AL3: cmp al, 'R'
jnz AL4
mov opt_RR, al
jmp short aloop
AL4: cmp al, '1'
jnz AL5
mov opt_1, al
jmp short aloop
AL5: cmp al, 'r'
jnz AL6
mov opt_r, al
jmp short aloop
AL6: cmp al, 't'
jnz AL7
mov opt_t, al
jmp short aloop
AL7: jmp prt_usage
adone:
call _shift
dec argc
jmp bigalp ; maybe he said -R -t or something like that
no_opts:
; sea_atr = directory; /* includes normal files */
; if (opt_a)
; sea_atr = hidden + directory;
mov sea_atr, 10h
test opt_a, -1
jz no_opta
mov sea_atr, 12h
no_opta:
; char fname[128];
mov cx, 128
call new
mov fname, bx
; if (argv > 1) error;
cmp argc, 1
jbe K1
prt_usage: mov cx, umsgl ; give syntax error
mov dx, offset umsg
mov bx, stderr ; write to error device...
dos 40h
mov al, 1 ; status = error
dos 4ch ; terminate process.
K1:
; fname[0] = '/0';
mov di, fname
mov byte ptr [di], 0
; if (argc = 1) strcpy(fname, argv[2]);
cmp argc, 1
jnz K2
mov si, argv[2];
arcloop: lodsb
cmp al, 0
stosb
jnz arcloop
K2:
;-------------------------------
; /* No argument, or default directory? */
; if (fname[0] == '\0' || (fname[0] == '.' && fname[1] == '\0'))
mov si, fname
lodsb
cmp al, 0
jz B3
cmp al, '.'
jnz K3
lodsb
cmp al, 0
jnz K3
B3:
; /* leave a drive specifier for next if statement */
; fname[0] = 'A' + current_drive;
; fname[1] = ':';
; fname[2] = '\0';
; }
dos 19h ; AL = disk (0=A, 1=B...)
mov di, fname
add al, 'A'
stosb
mov al, ':'
stosb
mov al, 0
stosb
K3:
;---------------------------
; /* Drive only? If so, get default directory for that drive */
; if (fname[1] == ':' && fname[2] == '\0') {
mov si, fname
inc si
lodsb
cmp al, ':'
jnz K4
lodsb
cmp al, 0
jnz K4
; fname[2] = '\';
; getpath(fname+3, toupper(fname[0])-'A'+1 );
; if (fname[3] != 0) /* root directory */
; strappend(fname, "\");
; }
;
mov byte ptr [si-1], '\'
mov dl, byte ptr [si-3]
sub dl, 'a'-1
ja islower
add dl, 32
islower:
; Note that SI is pointing to the char just after the slash.
dos 47h ; get cur dir of drive DL
mov si, fname
cmp byte ptr [si+3], 0
jz K4 ; if root, don't add slash.
L4: lodsb
cmp al, 0
jnz L4
mov byte ptr [si-1], '\'
mov byte ptr [si], 0
K4:
; /* Is it wildcarded? If so, it cannot be a directory. */
; for (i=0; i<strlen(fname); i++)
; wild = (fname[i] in ['?', '*']);
;
mov wild, -1
mov si, fname
L4A: lodsb
cmp al, '?'
jz K4A
cmp al, '*'
jz K4A
cmp al, 0
jnz L4A
mov wild, 0
K4A:
;--------------------------
; /* Is it a directory (does it end with a slash) ? */
; if (!wild && !(fname[len-1] in ['/', '\'])) {
test wild, -1
jnz K5
mov si, fname
L5: lodsb
cmp al, 0
jnz L5
sub si, 2 ; point to last nonnull
lodsb ; get it
cmp al, '\'
jz K5
cmp al, '/'
jz K5 ; if AL in ['/', '\'], skip IF clause.
; type = chmod(0, fname);
; if (type & directory) {
; strappend(fname, "\");
; }
mov dx, fname
; | kludge: if [dx] = "..", file is a directory...
push si
mov si, dx
mov di, offset dotdot
call strcmp
pop si
jz isdotdot
mov al, 0
DOS 43h
jc K5 ; not found- ergo not directory
and cl, 10h ; directory?
jz K5 ; nope; skip.
isdotdot: ; Note that SI still points to null @ end of string.
mov di, si
mov al, '\'
stosb
mov al, 0
stosb
K5:
; if (fname[len-1] in ['/', '\'])
mov si, fname
L6: lodsb
cmp al, 0
jnz L6
sub si, 2 ; point to last nonnull
lodsb ; get it
cmp al, '\'
jz B6
cmp al, '/'
jnz K6 ; if AL not in ['/', '\'], skip IF clause.
B6:
; strappend(fname, "*.*");
mov di, si
mov al, '*'
stosb
mov al, '.'
stosb
mov al, '*'
stosb
mov al, 0
stosb
mov si, di
K6:
call checkspec ; returns pointer to list in BX
call sort_struct ; sorts list, returning new BX
mov word ptr depth, 0
mov byte ptr pe_dp, 1
mov colcount, 0
call print_struct ; prints list
; If we haven't yet, finish off with a cr/lf.
cmp colcount, 0
jz all_done
mov dl, 13
DOS 2
mov dl, 10
DOS 2
all_done:
mov al, 0
DOS 4CH ; terminate
ls endp
;------
indent proc near
push cx
push dx
cmp colcount, 0
jnz noind
mov cx, depth
add cx, cx
add cx, depth
sub cx, 3
jbe noind
mov dl, ' '
LI1: DOS 2
loop LI1
noind: pop dx
pop cx
ret
indent endp
;----- Main Program Stuff --------------------------------------------
;----- Definition of local variables for checkspec -------------------
oldlen equ 0
dirsize equ 2
sibling equ 6 ; points to things at same level
kids equ 8 ; points to children
finder equ 10
f_name equ finder+30
f_attr equ finder+21
f_time equ finder+22
f_date equ finder+24
f_size equ finder+26
findlen equ 43 ; finder is 43 bytes long
;----- Definition of entries in the data structure -------------------------
e_size equ 0 ; longint; { totalled }
e_prev equ 4 ; entryptr; { entry found a moment ago }
e_kids equ 6 ; entryptr; { only nonzero for directories }
e_date equ 8 ; word;
e_time equ 10 ; word;
e_attr equ 12 ; byte; { only bit 3 counts during sort }
e_name equ 13 ; string[15]; { in lowercase, padded with nulls }
entrylen equ 28
;---------------------------------------------------------------------------
;---- Compare_Entries ---------------------------------------------------
; Called with one entryptr in SI, one in DI.
; Return with Carry set if di > si.
; Compare names unless -t, in which case compare dates×.
; Sort order is reversed if -r, except that results are always sorted
; to yield directories at the deepest part of the list.
compare_entries proc near
push si
push di
; compare attributes, to force pretty output.
; (That is, if DI is a directory and SI isn't, set carry.)
mov al,[si][e_attr]
mov ah,[di][e_attr]
and ax, 1010h ; mask out all but dir status
cmp al,ah
jnz comp_done ; we're done if not equal.
test opt_r, -1 ; reverse sort?
jz comp_norev ; nope.
xchg si, di ; yep.
comp_norev:
test opt_t, -1 ; sort by time?
jnz comp_times ; yes...
; Compare names.
mov cx, 15 ; length of name field in bytes
add si, e_name
add di, e_name ; point them to start of name field
rep cmpsb
jmp short comp_done
comp_times:
; Compare dates, then times.
xchg si, di
mov cx, 2
add si, e_date
add di, e_date
rep cmpsw
comp_done:
pop di
pop si
ret
compare_entries endp
;---- sort_list ----------------------------------------------------------
; procedure sort_list(var bx: entryptr);
;
; Sorts one list of the data structure. Caller must use the returned BX
; as his new pointer to the start of the list.
; Uses simple bubble sort.
;
; var
; fore, back, fartherback: entryptr;
; flip : boolean;
; begin
; if (bx != nil) then repeat
; flip := false;
; fartherback := &bx; { more or less }
; back := bx;
; fore := bx^.prev;
; while (fore != nil) do begin
; compare(si=fore, di=back);
; if carry then begin
; back^.prev := fore^.prev;
; fore^.prev := back;
; fartherback^.prev := fore;
; swap (fore, back);
; flip := true;
; end;
; fartherback := back;
; back := fore;
; fore := fore^.prev;
; end;
; until not flip;
; end;
;
; si = fore, di = back, bx = fartherback
root equ 0
flip equ 2
sort_list proc near
push bp
sub sp, 4 ; allocate locals (We don't need to be
mov bp, sp ; re-entrant, but what the heck)
mov [bp][root], bx
or bx, bx
jz sort_done;
sort_r: mov byte ptr [bp][flip], 0
lea bx, [bp][root] ; bx always points to a .prev
mov di, [bx] ; whereas *di is a whole record
mov si, [di][e_prev]
sort_w: or si, si
jz sort_wx ; while's exit
call compare_entries
; if carry then begin
; back^.prev := fore^.prev;
; fore^.prev := back;
; fartherback^.prev := fore;
; swap (fore, back);
; flip := true;
; end;
jae no_flippo
move [di][e_prev], [si][e_prev]
mov [si][e_prev], di
mov [bx], si
xchg si, di
mov byte ptr [bp][flip], -1
no_flippo:
; fartherback := back;
; back := fore;
; fore := fore^.prev;
lea bx, [di][e_prev]
mov di, si
mov si, [si][e_prev]
; end;
jmp sort_w
sort_wx:
; until not flip;
test byte ptr [bp][flip], -1
jnz sort_r
; end;
sort_done:
mov bx, [bp][root]
add sp, 4
pop bp
ret
sort_list endp
;---- sort_struct ---------------------------------------------------------
; procedure sort_struct(var bx: entryptr);
; { Sorts entire data structure. Caller must use returned BX. }
; begin
; sort_list(bx);
; while (bx != nil) do begin
; sort_list(bx^.kids);
; bx := bx^.prev;
; end;
; end;
sort_struct proc near
call sort_list
push bx
ss_w:
or bx, bx
jz ss_done
push bx
mov bx, [bx][e_kids]
call sort_struct
pop si
mov [si][e_kids], bx ; use new BX returned by Sort
mov bx, [si][e_prev]
jmp ss_w
ss_done:
pop bx
ret
sort_struct endp
page
;---- print_struct ---------------------------------------------------------
; procedure print_struct(bx: entryptr);
;
; Prints out the tree.
;
print_struct proc near
inc depth
ps_loop:
cmp bx, 0
jz ps_done
call printentry
push [bx][e_prev]
mov bx, [bx][e_kids]
cmp bx, 0
jz ps_nokids
call print_struct
ps_nokids: pop bx
jmp ps_loop
ps_done:
dec depth
ret
print_struct endp
;---- printentry -----------------------------------------------------------
;
; printentry(bx: entryptr);
; {
; /* Print the entry according to the options given */
; if (opt_a || !([bx][e_attr] && hidden)) {
;
; }
printentry proc near
test opt_a, -1
jnz doentry ; Unless -a option,
lea si, [bx][e_name]
lodsb
cmp al, '.'
jne doentry ; if starts with dot, don't print.
jmp peend
doentry:
test opt_1, -1
jnz doreturn
mov ax, depth
cmp al, pe_dp
jnz doreturn
mov cx, 15
test opt_s, -1
jz nosopt
mov cx, 25
nosopt: mov al, colcount
xor ah,ah
inc ax
mul cx
mov cx, depth
dec cx ; depends what start value is
add ax, cx
add ax, cx
add ax, cx
cmp ax, 80 ;?79
jnge noreturn
doreturn:
mov dl, 13
DOS 2
mov dl, 10
DOS 2
mov colcount, 0
noreturn:
test opt_l, -1
jnz nr1
jmp notpl
nr1:
push di
mov di, offset sattribs ;? is di available
; stuff for directory, temporary, or volumename (t/d/v)
test byte ptr [bx][e_attr], A_DIRECTORY
jz pe_nd
mov al, 'd'
jmp short pe_gotspecial
pe_nd: ; See if file created at 25 O'Clock (see BLAM.COM and SUICIDE.COM)
cmp word ptr [bx][e_time], (25 * 2048)
jnz pe_ntemp
mov al, 't'
jmp short pe_gotspecial
pe_ntemp:
mov al, '-'
pe_gotspecial:
stosb
mov al, '-'
; stuff for hidden -h
test byte ptr [bx][e_attr], A_HIDDEN
jz pe_nh
mov al, 'h'
pe_nh: stosb
mov al, '-'
; stuff for system -s
test byte ptr [bx][e_attr], A_SYSTEM ; (sic)
jz pe_ns
mov al, 's'
pe_ns:
stosb
mov al, '-'
; stuff for read -r
mov al, 'r'
stosb
mov al, '-'
; stuff for write -w
test byte ptr [bx][e_attr], A_READONLY
jnz pe_nr
mov al, 'w'
jmp short pe_gotr
pe_nr:
test byte ptr [bx][e_attr], A_DIRECTORY
jz pe_gotr
mov al, 'w'
pe_gotr:
stosb
push di
; stuff for executable -x
; executable = (directory || terminator in {.bat, .com, .exe})
test byte ptr [bx][e_attr], A_DIRECTORY
jnz pe_isx
lea si, [bx][e_name] ; get pointer to null-term name
mov al, '.'
call rindex ; get pointer to extension
or si, si
mov al, '-'
jz pe_gotx
inc si
mov ax, si ; save extension
mov di, offset EXT_COM
call strcmp
jz pe_isx
mov si, ax
mov di, offset EXT_EXE
call strcmp
jz pe_isx
mov si, ax
mov di, offset EXT_BAT
call strcmp
jz pe_isx
mov al, '-'
jmp short pe_gotx
pe_isx: mov al, 'x'
pe_gotx:
pop di
stosb
pop di
push bx
mov bp,sp
mov ax, [bx][e_date]
and ax, 31
push ax
mov ax, [bx][e_date]
mov cl, 5
shr ax, cl
and ax, 15
dec ax
add ax, ax
add ax, ax
add ax, offset months
push ax
mov ax, [bx][e_size]
mov dx, [bx][e_size+2]
push dx
push ax
mov ax, offset sattribs
;mov ax, [bx][e_attr] ; temporary until attributes printed
push ax
mov ax, offset lcontrol
push ax
mov ax, offset pbuffer
push ax
call sprintf
mov sp, bp
pop bx
call printbuff
DOS 2AH ;cx=year,dh=month,dl=day
mov ax, cx
sub ax, 1980
mov cl, 9
shl ax, cl
add al, dl
mov dx, ax ; this year's packed year
push bx
mov bp, sp
mov ax, [bx][e_date]
cmp ax, dx
jl doyear
add dx, 200H ; beginning of next year
cmp ax, dx
jl dotime
doyear: mov cl, 9
shr ax, cl
and ax, 127
add ax, 1980 ;1980 is base year for years
push ax
mov ax, offset ycontrol
jmp dofield
dotime: mov ax, [bx][e_time]
mov cl, 5
shr ax, cl
and ax, 63
push ax
mov ax, [bx][e_time]
mov cl, 11
shr ax, cl
and ax, 31
push ax
mov ax, offset tcontrol
dofield:
push ax
mov ax, offset pbuffer
push ax
call sprintf
mov sp, bp
pop bx
call printbuff
jmp dofile
notpl: test opt_s, -1
jz dofile
push bx
mov bp, sp
mov ax, [bx][e_size]
mov dx, [bx][e_size+2]
push dx
push ax
mov ax, offset scontrol
push ax
mov ax, offset pbuffer
push ax
call sprintf
mov sp, bp
pop bx
call printbuff
dofile: call indent
mov ax, depth
mov pe_dp, al
push bx
mov bp, sp
lea dx, [bx][e_name]
mov cx, 15
test byte ptr [bx][e_attr], 10H
jz notdir
cld
mov di, dx
mov al, 0
repnz scasb
mov byte ptr [di-1],'\'
notdir: lea ax, [bx][e_name]
push ax
mov ax, offset fcontrol
push ax
mov ax, offset pbuffer
push ax
call sprintf
mov sp, bp
pop bx
call printbuff
inc colcount
peend: ret
printentry endp
printbuff proc near
push bx
mov dx, offset pbuffer
mov cx, 90
cld
mov di, dx
mov al, 0
repnz scasb
mov cx, di
dec cx
mov dx, offset pbuffer
sub cx, dx
mov bx, stdout
DOS 40H
pop bx
ret
printbuff endp
;----- strlen -------
; Call it with string @ SI:DS.
; Returns with length in CX, and SI pointing to the null at end of string.
strlen proc near
mov cx, 0
SL1: lodsb
inc cx
cmp al, 0
jnz SL1
dec si
ret
strlen endp
;---- stripwild ---------
; Call with SI=start of string to strip.
stripwild proc near
push si
call strlen
pop di
dec di
std ; search from string end back
mov wild, 0 ; no wildcards found yet
SW_loop: lodsb
cmp al, '*'
jz sw_wild
cmp al, '?'
jnz sw_nw
sw_wild: mov wild, 1
sw_nw: cmp al, '\'
jz SW_gotit
cmp al, '/'
jz SW_gotit
cmp al, ':'
jz SW_gotit
cmp si, di
jnz SW_loop
SW_gotit:
cld
test wild, 1
jz SW_forgetit ; jump if no wilds found
add si, 2
mov byte ptr [si], 0
SW_forgetit:
ret
stripwild endp
;---- save_entry -------------------------------------------------------------
; To be called from within checkspec. Accesses local variables thereof.
;
; Places a record of the current entry into the data structure.
; Converts name to lowercase, pads to 15 nulls.
;
; procedure save_entry(bp: finderptr);
; var
; newentry: entryptr;
; begin
; new(newentry);
; with newentry^ do begin
; prev := [bp][sibling];
; [bp][sibling] := newentry;
; kids := [bp][kids];
; size := [bp][f_size];
; attr := [bp][f_attr];
; name := upperstring([bp][f_name]);
; pad(name, 15,0);
; end;
; end;
save_entry proc near
mov cx, entrylen
call new ; bx = newentry;
move [bx][e_prev], [bp][sibling]
mov [bp][sibling], bx
move [bx][e_kids], [bp][kids]
move [bx][e_size], [bp][f_size]
move [bx][e_size+2], [bp][f_size+2]
movb [bx][e_attr], [bp][f_attr]
move [bx][e_date], [bp][f_date]
move [bx][e_time], [bp][f_time]
lea si, [bp][f_name]
lea di, [bx][e_name]
mov cx, 15 ; Field is 15 bytes.
se_1: lodsb
cmp al, 'A'
jb se_2
cmp al, 'Z'
ja se_2
add al, 32
se_2: stosb
cmp al, 0
loopnz se_1
dec di
inc cx
mov al,0
rep stosb ; pad with nulls.
; only needs 1 (2 if a directory)
ret
save_entry endp
page
;------------------------------------------------------------------------
; /* checkspec finds and prints the name of each file */
; /* which matches the given filespec. */
; /* Also returns total size of all files in DX:AX. */
; /* Returns sibling list pointer in BX. */
; long checkspec;
; {
; int oldlen;
; int dirsize = 0;
; char finder[32];
;
; oldlen = strlen(fname);
; depth++;
; set_DTA(finder);
; findfirst(fname, finder, sea_atr);
; strip_wildcards(fname);
;
; do {
; dirsize += finder.size;
; printentry(finder.name);
; if (opt_RR && finder.type==directory && finder.name[0]!='.') {
; strcpy(fname+oldlen, finder.name, "\*.*");
; dirsize += checkdir;
; set_DTA(finder);
; }
; } while findnext;
;
; fname[oldlen]='\0';
; if (opt_s)
; printentry(fname);
; depth--;
; return(dirsize);
; }
page
; long checkspec() {
checkspec proc near
; 0 int oldlen;
; 4 long dirsize = 0;
; 6 word sibling = nil;
; 8 word kids = nil;
; 10 char finder[43];
locals equ finder+findlen
push bp
sub sp, locals ; allocate room for locals
mov bp, sp
; dirsize = 0; sibling = nil; kids = nil;
mov word ptr [bp][dirsize], 0
mov word ptr [bp][dirsize+2], 0
mov word ptr [bp][sibling], 0
; mov word ptr [bp][kids], 0
; set_DTA(finder);
lea dx, [bp][finder]
DOS 1AH
; findfirst(fname, finder, attribs(opt_a));
mov dx, fname
mov cx, 10H
test opt_a, -1
jz findem
mov cx, 17H
findem: DOS 4EH
jc while ; if none found, skip whole business.
; strip_wildcards(fname); /* kill everything back to slash */
mov si, fname
call stripwild
mov si, fname
call strlen
mov [bp][oldlen], si
; while (found) do {
clc
while: jc endwhile
; dirsize += finder.size;
mov ax, [bp][f_size]
add [bp][dirsize], ax
mov ax, [bp][f_size+2]
adc [bp][dirsize+2], ax
; finder.kids := nil;
; ( In case last time thru was a directory. }
mov word ptr [bp][kids], 0
; if (opt_RR && finder.type == directory) {
test opt_RR, -1
jz KC2
test byte ptr [bp][f_attr], 10h
jz KC2
; strcpy(fname+oldlen, finder.name, "\*.*");
mov di, [bp][oldlen]
lea si, [bp][f_name]
cmp byte ptr [si], '.' ; is it "." or ".." ?
jz KC2 ; if so, don't recurse!!!!
LC2: lodsb
cmp al, 0
jz BC2
stosb
jmp LC2
BC2: mov al, '\'
stosb
mov al, '*'
stosb
mov al, '.'
stosb
mov al, '*'
stosb
mov al, 0
stosb
call checkspec
; finder.kids := checkspec.sibling;
; ( This is only to pass to save_entry. }
mov [bp][kids], bx
; dirsize += checkspec.length;
add [bp][dirsize], ax
adc [bp][dirsize+2], dx
; finder.size += checkspec.length;
add [bp][f_size], ax
adc [bp][f_size+2], dx
; set_DTA(finder);
lea dx, [bp][finder]
DOS 1AH
; }
KC2: call save_entry
; } while findnext;
DOS 4FH
JMP WHILE
endwhile:
; fname[oldlen]='\0';
mov si, [bp][oldlen]
mov byte ptr [si], 0
; return(dirsize, sibling);
; }
mov ax, [bp][dirsize]
mov dx, [bp][dirsize+2]
mov bx, [bp][sibling]
add sp, locals
pop bp
ret
checkspec endp
code ends
end ls