home *** CD-ROM | disk | FTP | other *** search
- ;************************** POPD.ASM ************************************
- ;
- ; POPD.ASM version 1.2
- ;
- ; Usage:
- ; POPD
- ; Will change to the most recently stored directory on
- ; the stack.
- ; POPD +n
- ; Will delete the directory stored in position n from
- ; the bottom of the stack, starting at one on the bottom.
- ; Purpose: This program will either change to the topmost directory
- ; on the stack created by PUSHD v. 1.1 (first usage), OR
- ; will delete from the stack the directory stored at position
- ; n, where 1 is the bottom of the stack. In either case,
- ; the program will compress the stack, to remove any empty
- ; storage space, and will update the position for the next
- ; storage accordingly.
- ; Preconditions:
- ; 1) PUSHD must be hooked to interrupt 13.
- ; 2) PUSHD must have the same commands from beginning
- ; to after definition of push6d, so that it knows how
- ; to access the resident code of PUSHD. (This includes
- ; the fact that there are 6 locations for directory storage
- ; which are 67 bytes in size.)
- ; 3) PUSHD must have the signature "PUSHD VERSION 1.1".
- ; 4) PUSHD must look for 7788 in ax and 7789 in bx for
- ; a call to int 13.
- ; 5) PUSHD must put the value of 7789 into ax and 7788
- ; into bx upon calling int 13 by DIRS, if PUSHD is installed.
- ; 6) PUSHD will set the data segment to be equal to the data
- ; segment that PUSHD used to install itself.
- ; 7) DS:[nextpush] (ds of PUSHD installation) must hold
- ; the location of the next empty directory stack location.
- ; Postconditions:
- ; 1) An appropriate error message will be printed out on
- ; standard error, OR
- ; 2) DS:[nextpush] will be decremented by one directory
- ; storage unit (67 bytes) AND EITHER:
- ; 2a) the current directory will become the directory on
- ; top of the stack (usage #1) OR
- ; 2b) the current directory will remain the same, but the
- ; targeted directory (1-6) will be deleted with the
- ; directories on the stack above shifted down one storage
- ; unit.
- ; 3) An error code will be generated.
- ; Error Codes:
- ; 0) Successful completion.
- ; 249) Error popping directory.
- ; 250) Directory Stack is empty.
- ; 251) Command Line parameter exceeds Directory Stack depth.
- ; 252) Illegal Characters on the Command Line.
- ; 253) Command Line parameter not in valid directory range (1-6).
- ; 254) Invalid Command Line delimiter.
- ; 255) PUSHD is not installed.
- ; Version changes:
- ; POPD v. 1.2: July 23, 1990.
- ; enhanced code using suggestions from David
- ; Kirschbaum (Toad Hall).
- ; "cleaned out" directory stack characters that
- ; were left after a POPD, which might not be over-
- ; written on next PUSHD.
- ; POPD v. 1.1: July 14, 1990.
- ; added "+n" option.
- ; changed hooked interrupt to 13 from 16.
- ; added error codes for abnormal termination.
- ; changed writes from vector 9 to vector 40h of
- ; int 21h.
- ; changed program termination from int 20h to vector
- ; 4Cxxh int 21h, where xx represents the error code
- ; generated.
- ; removed stack wrap around.
- ; POPDIR v. 1.0: Copyright 1986, Ziff-Davis Publishing Co.
- ; From PC Magazine, May 27, 1986
- ; No changes.
- ; Future Enhancements:
- ; 1) Change the "n" parameters so that it refers to the
- ; top of the stack, not the bottom (RELATIVE from the top
- ; NOT ABSOLUTE from the bottom).
- ; 2) Make program an .EXE file.
- ; 3) Correct error caused by 3 or more blanks on the
- ; end of the command line tail.
- ; 4) Add a help option, ?, from the command line.
- ; 5) Add -c option to clear ALL directories on stack.
- ; 6) Add -n option to clear n topmost directories on stack.
- ;
- ; Created by:
- ; (from ideas based in UNIX and from PC Magazine's POPDIR.COM)
- ; William P. Sarra
- ; CIS:71041,347
- ; arpa: sarra@TOPAZ.RUTGERS.EDU
- ; uucp: ...{ames,cbosgd, harvard, moss}!rutgers!topaz.rutgers.edu!sarra
- ;
- ;*****************************************************************************
-
- main group CSEG
- CSEG segment public para 'code'
- ASSUME CS:MAIN,DS:MAIN,ES:MAIN,SS:MAIN
-
- org 80h
- cmd_line label byte
-
- org 100h ;.COM file
-
- BEGIN: jmp Start ;program starts here
-
- signature db 'PUSHD VERSION 1.1'
- SIG_LEN equ $-signature
-
- savedint13 dd ? ;used to be identical to pushd
-
- nextpush dw offset MAIN:push1d ;next place to save a dir
-
- push1d db 67 dup (0)
- push2d db 67 dup (0)
- push3d db 67 dup (0)
- push4d db 67 dup (0)
- push5d db 67 dup (0)
- push6d db 67 dup (0)
-
- ;up to here must be EXACTLY identical in PUSHD, POPD and DIRS.
-
- ;****************************************************************
- ;
- ; Data Section.
- ;
- ;****************************************************************
-
- not_inst db 'Must run PUSHD.COM before POPD.COM'
- db ' will do anything.',13,10,10
- NOT_INST_LN equ $-not_inst
- errpop1 db 'Error popping the current directory',13,10,10
- ERRPOP1_LN equ $-errpop1
- empty_stack db 'No directories on the stack.',13,10
- EMPTY_STACK_LN equ $-empty_stack
-
- BLANK equ 20h ;' '
- DELIMITER equ 2Bh ;'+'
-
- LOW_LIMIT equ 31h ;'1'
- UP_LIMIT equ 36h ;'6'
-
- bad_delim db 'Invalid Delimiter.',13,10
- BAD_DELIM_LN equ $-bad_delim
- in_dir_msg db 'Valid directories range between 1 and 6.',13,10
- IN_DIR_MSG_LN equ $-in_dir_msg
- bs_online db 'Invalid Command Line Parameters.',13,10
- BS_ONLINE_LN equ $-bs_online
- not_pushed db 'Parameter exceeds Directory Stack depth.',13,10
- NOT_PUSHED_LN equ $-not_pushed
-
- params db ? ;storage for command line tail
-
- targ_dir dw offset main:push1d ;address storage
-
- ;*******************************************************************
- ;
- ; Code Starts.
- ;
- ;*******************************************************************
-
- START:
-
- ;get and store command line tail as it may get destroyed
-
- cld
-
- ;v1.2 I entirely rewrote this section. What a kludge!
-
- mov si,offset cmd_line ;command line tail
- lodsb ;snarf length byte, bump SI
-
- ;SI -> first char (probably a space!)
-
- xor ah,ah ;clear msb
- mov cx,ax ;into CX
- push ax ;save length on stack for later
- jcxz INST_CHK ;CX is 0, branch
-
- ;We have a non-null command line
-
- mov di,offset MAIN:params ;store since it may get
- rep movsb ;destroyed
-
- INST_CHK:
-
- ;is PUSHD already installed ?
-
- mov ax,7788h ;signature request
- mov bx,7789h ;signature request
- mov si,offset MAIN:signature ;point ds:si to signature
- int 13h ;is it installed ?
-
- ASSUME DS:CSEG ;assume TSR's DS v1.2
-
- cmp bx,7788h ;were ax and bx switched ?
- jne NOTINSTALLED ;no
- cmp ax,7789h ;were ax and bx switched ?
- je ISINSTALLED ;v1.2
-
- NOTINSTALLED:
-
- ;PUSHD is not installed, terminate with an error message.
-
- mov dx,offset MAIN:not_inst ;error message
- mov cx,NOT_INST_LN
- mov al,0FFH ;ERRORLEVEL v1.2
- jmp Msg_Term ;display, terminate v1.2
-
- ISINSTALLED:
-
- ; check for command line parameters
-
- pop cx ;get saved cx
- push DS ;store current ds
-
- mov ax,CS ;v1.2
- mov DS,ax ;v1.2
- ASSUME DS:MAIN ;reminder v1.2
-
- or cx,cx ;check for no parameters
- jnz ERR1
- jmp CHK_STACK
-
- ERR1: mov di,offset MAIN:params
- mov al,BLANK ;remove leading blanks
- repe scasb
- dec di
- inc cx
- mov si,di ;save position
- lodsb ;snarf first char, bump SI v1.2
- cmp al,BLANK ;space? v1.2
-
- jne ERR2
- jmp CHK_STACK ;only blanks on tail
- ERR2:
- cmp al,DELIMITER ;is it '+' delimiter? v1.2
- je CHK_VALUE
-
- ;Current character is not valid -- Print error message and exit
-
- mov dx,offset MAIN:bad_delim ;bad delimiter message
- mov cx,BAD_DELIM_LN
- mov al,0FEH ;ERRORLEVEL v1.2
- jmp Msg_Term ;display, terminate v1.2
-
- CHK_VALUE:
-
- ;check that parameter values are within specified limits
-
- dec cx
-
- ;v1.2 Recoded
- lodsb ;snarf digit after '+', bump SI
- cmp al,UP_LIMIT ;above '6'?
- ja INVALID_DIR ;yep, bogus
- cmp al,LOW_LIMIT ;below '1'?'
- jnb FINISH_CHK ;nope, in range ['1'..'6']
-
- INVALID_DIR:
-
- ;invalid directory number -- print message and exit
-
- mov dx,offset MAIN:in_dir_msg ;error message
- mov cx,IN_DIR_MSG_LN
- mov al,0FDH ;ERRORLEVEL v1.2
- jmp Msg_Term ;display, terminate v1.2
-
- FINISH_CHK:
-
- ;continue checking for invalid characters on the command line
- ; after getting valid characters.
-
- dec cx ;decr cmdline count for digit v1.2
- jcxz VALID_DIR
-
- mov ah,al ;save digit v1.2
- mov al,BLANK ;check for following nonblank
- repne scasb ;characters
- mov al,ah ;replace digit v1.2
-
- jcxz VALID_DIR
-
- ;Invalid characters on the command line -- print message and
- ; exit
-
- mov dx,offset MAIN:bs_online ;error message
- mov cx,BS_ONLINE_LN
- mov al,0FCH ;ERRORLEVEL v1.2
- jmp Msg_Term ;display, terminate v1.2
-
- VALID_DIR:
-
- ;get stack location of targeted directory
-
- xor ah,ah ;clear ah v1.2
- mov cx,67 ;multiplier v1.2
- sub al,'1' ;'0'..'5' range
- mul cx ;directory offset v1.2
- add ax,offset MAIN:push1d ;base directory buffer v1.2
- mov targ_dir,ax ;save it v1.2
-
- CHK_DIR:
-
- ;check that the directory stack depth is at least to
- ; the targeted directory location
-
- pop DS ;restore ds
- ASSUME DS:CSEG ;reminder v1.2
-
- mov bp,DS:[nextpush] ;get location of last
- sub bp,67 ;pushed directory
- cmp bp,CS:[targ_dir] ;make sure directory stack
- jge PROCESS_DIRS ;is deep enough for params
-
- ;the parameter number "n" exceeds the depth of the directory stack
- ; print a message and exit with an error
-
- mov dx,offset MAIN:not_pushed ;error message
- mov cx,NOT_PUSHED_LN
- mov al,0FBH ;ERRORLEVEL v1.2
- jmp Msg_Term ;display, terminate v1.2
-
- PROCESS_DIRS:
-
- ;stack is deep enough, if the targeted directory location is
- ; at the top of the stack, simply decrement ds:[nextpush],
- ; effectively erasing the top directory and exit successfully.
-
- jne NOT_TOP ;check on popping top of stack, set
- mov DS:[nextpush],bp ;nextpush to be top of current stack
- jmp SHORT EXITING
-
- NOT_TOP:
-
- ;targeted directory is in the middle of stack, so decrement
- ; DS:[nextpush] to reflect stack deletion, set the current location
- ; to be the targeted stack location, and...
-
- mov DS:[nextpush],bp ;set nextpush to top of stack
- mov bp,CS:[targ_dir] ;set bp to be targeted directory
- mov ax,DS ;v1.2
- mov ES,ax ;v1.2
- ASSUME ES:CSEG ;reminder v1.2
-
- ;handy constants v1.2
- mov dx,DS:[nextpush] ;v1.2
- mov ax,67 ;v1.2
- mov bx,bp ;v1.2
-
- DIR_LOOP:
-
- ;...cycle through the stack copying the contents of the directory
- ; above the current location into the current location...
-
- add bp,ax ;go to next pushed directory v1.2
- cmp bp,dx ;DS:[nextpush] v1.2
- je LAST_DIR ;found the last directory
- mov si,bp ;copy contents to
- mov di,bx ;targ_dir v1.2
- mov cx,ax ;67 v1.2
- rep movsb
- add bx,ax ;targ_dir,67 v1.2
- jmp SHORT DIR_LOOP ;continue
-
- LAST_DIR:
-
- ;...until the last directory is copied into the nearest lower
- ; storage location
-
- mov si,bp ;one more copy
- mov di,bx ;targ_dir v1.2
- mov cx,ax ;67 v1.2
- rep movsb
- jmp SHORT EXITING ;exit successfully
-
- CHK_STACK:
-
- ;handle parameterless command
-
- ;get the location of the directory most recently saved by pushd
- ; (top of stack)
-
- pop DS ;restore ds
- ASSUME DS:CSEG ;reminder v1.2
-
- mov bp,DS:[nextpush] ;get the next push location
- sub bp,67 ;back up one to the last push
- cmp DS:[nextpush],offset MAIN:push1d ;empty stack?
- jne NOTEMPTY ;no
-
- ;directory stack is empty (ds:[nextpush] = location of first
- ; storage location) -- print message and exit with error
-
- mov dx,offset MAIN:empty_stack ;error message
- mov cx,EMPTY_STACK_LN
- mov al,0FAH ;ERRORLEVEL v1.2
- jmp Msg_Term ;display terminate v1.2
-
- NOTEMPTY:
-
- ;directory stack is not empty -- change to directory on top of
- ; stack
-
- ;set the current directory
-
- mov dx,bp ;load DS:dx with directory to set
- mov ah,3bh ;dos function number
- int 21h ;set current dir back
- jc ERRPOP ;branch on error
-
- ;set the current drive if previous commands are successful
-
- mov al,DS:[bp] ;get drive letter from path
- sub al,'A' ;convert to binary (0=A, 1=B)
- mov dl,al
- mov ah,0eh ;dos function number
- int 21h ;set drive
- jc ERRPOP
-
- mov DS:[nextpush],bp ;update [nextpush] if successful
-
- EXITING:
-
- ;clear up previous directory storage v1.2
-
- mov ax,DS ;v1.2
- mov ES,ax ;v1.2
- ASSUME ES:CSEG ;reminder v1.2
-
- mov cx,67 ;v1.2
- mov di,DS:[nextpush] ;v1.2
- mov al,BLANK ;v1.2
- rep stosb ;v1.2
-
- ;exit successfully with no message
-
- mov ax,4c00h
- int 21h ;exit
-
- ERRPOP:
-
- ;An error occurred while attempting to change to targeted
- ; directory -- print error message and exit with error
-
- mov dx,offset MAIN:errpop1 ;error message
- mov cx,ERRPOP1_LN
- mov al,0F9H ;ERRORLEVEL v1.2
- ; jmp Msg_Term ;display, terminate v1.2
-
- ;*********************************************************************
- ;
- ; PROCEDURE: Msg_Term
- ;
- ; Purpose: This procedure will handle the printing of error messages
- ; and termination with the correct errorlevel.
- ; Preconditions:
- ; DX = error message address.
- ; CX = error message length.
- ; AL = ERRORLEVEL.
- ; Postconditions:
- ; The program will be terminated with the appropriate
- ; error message printed on standard error and with the
- ; the errorlevel stored in al.
- ;
- ;***************************************************************************
-
- Msg_Term PROC NEAR
- ;v1.2 Common routine to display error messages and terminate.
-
- push CS ;insure this is so
- pop DS
- ASSUME DS:MAIN
-
- push ax ;save ERRORLEVEL in AL
- mov bx,2 ;write to stderr
- mov ah,40h ;dos function number
- int 21h ;show error message
- pop ax ;restore ERRORLEVEL in AL
- mov ah,4CH ;terminate process
- int 21h
-
- Msg_Term ENDP
-
-
- CSEG ends
- end BEGIN ;start execution at BEGIN
-