home *** CD-ROM | disk | FTP | other *** search
- ; DIRS.ASM
- ; (c) 1989, 1990 Ashok P. Nadkarni
- ;
- ;This module implements the directory stack feature of the cmdedit program.
-
- INCLUDE ascii.inc
- INCLUDE common.inc
- INCLUDE general.inc
- INCLUDE buffers.inc
- INCLUDE dos.inc
- INCLUDE bios.inc
-
- PUBLIC dirs_init
- PUBLIC execute_popd
- PUBLIC execute_pushd
- PUBLIC execute_chd
- PUBLIC execute_rstdir
- PUBLIC enable_dircmds
-
- PATHBUF_SIZE EQU 68
-
- CSEG SEGMENT PARA PUBLIC 'CODE'
-
- EXTRN user_command:BYTE
- EXTRN in_appl:BYTE
- EXTRN linebuf:BYTE ;line buffer
- EXTRN lastchar:WORD
- EXTRN dirstk_error:BYTE
- EXTRN resident:BYTE
- EXTRN abort_install:PROC
- EXTRN abort_processing:PROC
- EXTRN skip_whitespace:PROC
- EXTRN skip_nonwhite:PROC
- EXTRN tolower:PROC
-
- dir_stk $string_stack <> ;Buffer descriptors
- enable_dircmds db 1 ;If 1, enables directory commands
- ; even if caller is not DOS
-
- DGROUP GROUP CSEG
- ASSUME CS:DGROUP,DS:DGROUP,ES:DGROUP,SS:DGROUP
-
-
- ;+
- ; FUNCTION : dirs_init
- ;
- ; Initializes the various data structures associated with the
- ; directory stack buffer. CALLER MUST ENSURE PASSED ADDRESSES ARE VALID
- ; AND BUFFER IS LARGE ENOUGH.
- ;
- ; Parameters:
- ; AX - length of buffer in bytes
- ; BX - address of buffer
- ;
- ; Returns:
- ; AX = 0 if no errors
- ; -1 otherwise
- ; Registers destroyed : BX
- ;-
- dirs_init proc near
- push bx
- mov bx,offset DGROUP:dir_stk ;bx := address of buffer descriptors
- xchg ax,cx ;CX = buffer size
- pop ax ;AX = Buffer address
- ;BX points to appropriate descriptor
- call near ptr strstk_init ;Initialize buffer and descriptor
- ret
- dirs_init endp
-
-
- ;+
- ; FUNCTION: execute_rstdir
- ;
- ; Called to reset the directory stack.
- ;
- ; Parameters:
- ; None.
- ;-
- execute_rstdir proc near
- mov bx,offset DGROUP:dir_stk
- call near ptr strstk_reset
- ret
- execute_rstdir endp
-
- ;+
- ; FUNCTION : dir_push
- ;
- ; Called to push a drive and path onto the directory stack. The
- ; string must end in a 0 byte.
- ;
- ; Parameters:
- ; DX ->string to push
- ;
- ; Returns:
- ; CF = 1 if errors
- ; 0 no errors
- ;
- ; Register(s) destroyed:
- ; AX,BX,CX,DX
- ;-
- dir_push proc near
- @save di
- mov di,dx ;di->string
- mov cx,0ffffh
- xor al,al
- repne scasb
- mov ax,cx
- not ax ;AX<-length of string
- ; including null terminator
- mov bx,offset DGROUP:dir_stk
- xor cx,cx ;Don't force push
- call near ptr strstk_push ;Params AX,BX,CX,DX
- ; strstk_push sets/resets CF
- @restore
- ret
- dir_push endp
-
- ;+
- ; FUNCTION : abort_dir_op
- ;
- ; Called to abort a directory stack operation. Action taken
- ; depends on whether the program is already resident or is being
- ; installed. This routine does NOT return to caller.
- ;
- ; Parameters:
- ; AX = code to pass to abort_processing
- ;
- ; Returns:
- ; Nothing.
- ; Register(s) destroyed:
- ;-
- abort_dir_op proc near
- mov dx,offset DGROUP:abort_processing
- cmp resident,0
- jne @abort_dir_op_90 ;Jump if resident
- @DispStr dirstk_error
- mov dx,offset DGROUP:abort_install
- @abort_dir_op_90:
- jmp dx
- abort_dir_op endp
-
-
-
-
- ;+
- ; FUNCTION : check_dircmd_allowed
- ;
- ; Makes sure DOS is the caller or directory commands have been
- ; enabled for all applications and returns. Else aborts.
- ;
- ; Parameters:
- ; None.
- ;
- ; Returns:
- ; Nothing.
- ; Register(s) destroyed:
- ; AX
- ;-
- check_dircmd_allowed proc near
- cmp enable_dircmds,1
- je @check_dircmd_allowed_99
- mov ax,E_DIRSTK_DOS ;Assume error
- cmp in_appl,1 ;In application ?
- je abort_dir_op ;Yes, abort
- @check_dircmd_allowed_99: ;Else return
- ret
- check_dircmd_allowed endp
-
-
- ;+
- ; FUNCTION : save_drv_path
- ;
- ; Saves the current drive and path in the specified buffer in the
- ; form `D:\dir1....' where the current drive letter. The buffer
- ; MUST be long enough.
- ;
- ; Parameters:
- ; AX = address of save buffer
- ;
- ; Returns:
- ; Nothing.
- ;
- ; Register(s) destroyed:
- ; AX,DX
- ;-
- save_drv_path proc near
- @save si,di
- mov di,ax ;DI->save buffer
- @GetDrv ;AL<-drive number
- add al,'a' ;AL<-drive letter
- stosb ;Remember current drive
- mov al,':'
- stosb
- mov al,'\'
- stosb
- @GetDir di ;Remember current path
- @restore
- ret
- save_drv_path endp
-
-
-
- ;+
- ; FUNCTION : change_drv_path
- ;
- ; Changes the current drive and directory to the one specified.
- ;
- ; Parameters:
- ; AX ->path in the form `D:\dir1\dir2\...' terminated
- ; with a 0 byte where D is the drive letter. Entire
- ; path name need no be given. It is OK if the last
- ; directory in the path is followed by a '\'.
- ;
- ; Returns:
- ; CF = 0 if current drive and directory succesfully changed,
- ; 1 if any errors (drive and path both unchanged)
- ; Register(s) destroyed:
- ;-
- change_drv_path proc near
- @save si,di
- push bp
- mov bp,sp
- sub sp,PATHBUF_SIZE
- cur_path equ <byte ptr [bp-PATHBUF_SIZE]>
- push ax ;Remember new path
- lea ax,cur_path ;AX->current path save buf
- call near ptr save_drv_path ;Save current disk/dir
- pop dx ;DX->new path
- mov si,dx ;SI->new path
- mov di,dx
- xor al,al ;Search for terminator
- mov cx,0ffffh
- repne scasb ;DI->byte after NULL
- cmp byte ptr [di-2],'\' ;Extra '\' char ?
- jne @change_drv_path_10 ;No
- ;If '\' at the end, make sure it is not of the form d:\ or just \
- cmp byte ptr [di-3],':'
- je @change_drv_path_10
- dec di
- dec di ;DI->'\' character
- cmp di,dx ;Solitary '\' ?
- je @change_drv_path_10 ;Yes
- mov [di],al ;No, replace '\' with 0
- @change_drv_path_10:
- @ChDir dx
- jnc @change_drv_path_80 ;No error
- ; Check if error was because drive was specified but not the path.
- ; In this case, we should only change the drive.
- cmp byte ptr 2[si],0 ;third byte nust be null
- jne @change_drv_path_85 ;Nope
- cmp byte ptr 1[si],':' ;Drive specified ?
- jne @change_drv_path_85 ;Nope
- jmp short @change_drv_path_82
- @change_drv_path_80:
- cmp byte ptr 1[si],':' ;Drive spec ?
- clc ;To indicate success
- jne @change_drv_path_99 ;No, all done
- @change_drv_path_82:
- lodsb ;AL<-drive
- call near ptr tolower
- sub al,'a' ;AL<-drive number
- @SetDrv al ;Change the drive
- jnc @change_drv_path_99 ;No error
- ; Error, restore path, drive would not have been changed
- @change_drv_path_85:
- lea dx,cur_path
- @ChDir dx
- stc ;Indicate error to caller
- @change_drv_path_99:
- mov sp,bp
- pop bp
- @restore
- ret
- change_drv_path endp
-
-
-
- ;+
- ; FUNCTION : execute_popd
- ;
- ; Pops the topmost element off the directory stack and makes it
- ; the current drive/directory.
- ;
- ; Parameters:
- ; None.
- ;
- ; Returns:
- ; Nothing.
- ;
- ; Register(s) destroyed:
- ; AX,BX,CX,DX
- ;-
- execute_popd proc near
- call near ptr check_dircmd_allowed
- @save si,di
- push bp
- mov bp,sp
- sub sp,PATHBUF_SIZE
- topdir equ PATHBUF_SIZE
- mov bx,offset DGROUP:dir_stk ;BX->dir stack descriptor
- call near ptr strstk_settop
- lea ax,[bp-topdir]
- mov cx,PATHBUF_SIZE
- call near ptr strstk_copy ;Get top of stack
- ; String is terminated
- ; by a 0 byte
- jc @execute_popd_90
- or ax,ax ;Empty stack ?
- jz @execute_popd_90 ;Yes, error
- lea ax,[bp-topdir] ;AX->new path
- call near ptr change_drv_path ;Change drive and path
- jc @execute_popd_90
- call near ptr strstk_kill ;Delete top of stack
- mov sp,bp
- pop bp
- @restore
- ; Klugery - return a zero length string to DOS in order to set prompt properly.
- mov lastchar,offset DGROUP:linebuf
- mov user_command,1 ;indicate line to be
- ; returned to DOS
- ret
-
- @execute_popd_90:
- mov ax,E_DIRSTK_EMPTY
- jmp near ptr abort_dir_op
- execute_popd endp
-
-
-
- ;+
- ; FUNCTION : execute_pushd
- ;
- ; If a parameter is given, pushes current directory/disk onto the
- ; dir stack and changes to the parameter. If no parameter,
- ; exchange the top of directory stack with current disk-directory.
- ;
- ; Parameters:
- ; SI -> first char in linebuf following this command
- ; CX = remaining num chars in line
- ;
- ; Returns:
- ; Nothing.
- ;
- ; Register(s) destroyed:
- ; AX,BX,CX,DX
- ;-
- execute_pushd proc near
- @save si,di
- push bp
- mov bp,sp
- sub sp,2*PATHBUF_SIZE
- cur_path equ <byte ptr [bp-PATHBUF_SIZE]>
- new_path equ <byte ptr [bp-(2*PATHBUF_SIZE)]>
- call near ptr check_dircmd_allowed
- ; Will return only if so
- push cx ;Save line length
- lea ax,cur_path
- call near ptr save_drv_path ;Save current drive and path
-
- pop cx ;CX<-restored line length
- call near ptr skip_whitespace
- ; SI->first non blank, CX<-num remaining chars
- jcxz @execute_pushd_50 ;Exchange directory
- ; with top of stack
- push si ;SI->path to change to
- call near ptr skip_nonwhite
- ; SI->first non-blank
- mov byte ptr [si],0 ;Terminating 0 byte
- ; We are guaranteed place for a 0 because of the dummy byte after linebuf
- pop ax ;AX->dir to change to
- call near ptr change_drv_path ;Change path and drive
- jc @execute_pushd_32 ;Error
- @execute_pushd_25:
- lea dx,cur_path
- call near ptr dir_push ;Push onto stack
- jnc @execute_pushd_100 ;No error
- @execute_pushd_30:
- ; Error. Restore original directory and display error message.
- lea ax,cur_path
- call near ptr change_drv_path
- @execute_pushd_32:
- mov ax,E_DIRSTK
- jmp abort_dir_op
-
- @execute_pushd_50:
- ; Exhange current directory with the directory at the top of the stack
- mov bx,offset DGROUP:dir_stk ;BX->dir stack descriptor
- call near ptr strstk_settop
- lea ax,new_path
- mov cx,PATHBUF_SIZE
- call near ptr strstk_copy ;Get top of stack
- ; String is terminated
- ; by a 0 byte
- jnc @execute_pushd_60
- @execute_pushd_55:
- lea ax,cur_path
- call near ptr change_drv_path
- mov ax,E_DIRSTK_EMPTY
- jmp abort_dir_op
- @execute_pushd_60:
- or ax,ax ;Empty stack ?
- jz @execute_pushd_55 ;Yes, error
- lea ax,new_path ;AX->new path
- call near ptr change_drv_path ;Change drive and path
- jc @execute_pushd_30
- call near ptr strstk_kill ;Delete top of stack
- lea dx,cur_path
- call near ptr dir_push
- jnc @execute_pushd_100 ;All set
- ; Error. Restore original top of stack
- lea dx,new_path
- call near ptr dir_push ;Push must succeed
- jmp short @execute_pushd_30
-
- @execute_pushd_100:
- mov sp,bp
- pop bp
- @restore
- ; Klugery - return a zero length string to DOS in order to set prompt properly.
- mov lastchar,offset DGROUP:linebuf
- mov user_command,1 ;indicate line to be
- ; returned to DOS
- ret
- execute_pushd endp
-
-
-
-
- ;+
- ; FUNCTION : execute_chd
- ;
- ; Changes to the disk and directory specified as parameter.
- ;
- ; Parameters:
- ; SI -> first char in linebuf following this command
- ; CX = remaining num chars in line
- ;
- ; Returns:
- ; Nothing.
- ;
- ; Register(s) destroyed:
- ; AX,BX,CX,DX
- ;-
- execute_chd proc near
- @save si,di
- push bp
- mov bp,sp
- sub sp,PATHBUF_SIZE
- new_path equ <byte ptr [bp-PATHBUF_SIZE]>
- call near ptr check_dircmd_allowed
- ; Will return only if so
- push cx ;Save line length
- call near ptr skip_whitespace
- ; SI->first non blank, CX<-num remaining chars
- jcxz @execute_chd_100 ;No args
- ; with top of stack
- push si ;SI->path to change to
- call near ptr skip_nonwhite
- ; SI->first non-blank
- mov byte ptr [si],0 ;Terminating 0 byte
- ; We are guaranteed place for a 0 because of the dummy byte after linebuf
- pop ax ;AX->dir to change to
- call near ptr change_drv_path ;Change path and drive
- jnc @execute_chd_100 ;No error
- mov ax,E_DIRSTK
- jmp abort_dir_op
-
- @execute_chd_100:
- mov sp,bp
- pop bp
- @restore
- ; Klugery - return a zero length string to DOS in order to set prompt properly.
- mov lastchar,offset DGROUP:linebuf
- mov user_command,1 ;indicate line to be
- ; returned to DOS
- ret
- execute_chd endp
-
-
-
-
-
- CSEG ENDS
-
- END