home *** CD-ROM | disk | FTP | other *** search
/ World of Shareware - Software Farm 2 / wosw_2.zip / wosw_2 / CPROG / CMDSRC.ZIP / DIRS.ASM < prev    next >
Assembly Source File  |  1990-04-29  |  12KB  |  485 lines

  1. ; DIRS.ASM
  2. ; (c) 1989, 1990 Ashok P. Nadkarni
  3. ;
  4. ;This module implements the directory stack feature of the cmdedit program.
  5.  
  6.     INCLUDE ascii.inc
  7.     INCLUDE common.inc
  8.     INCLUDE general.inc
  9.     INCLUDE    buffers.inc
  10.     INCLUDE dos.inc
  11.     INCLUDE bios.inc
  12.  
  13.     PUBLIC    dirs_init
  14.     PUBLIC    execute_popd
  15.     PUBLIC    execute_pushd
  16.     PUBLIC    execute_chd
  17.     PUBLIC    execute_rstdir
  18.     PUBLIC    enable_dircmds
  19.  
  20. PATHBUF_SIZE EQU 68
  21.  
  22. CSEG    SEGMENT    PARA PUBLIC 'CODE'
  23.  
  24.     EXTRN    user_command:BYTE
  25.     EXTRN    in_appl:BYTE
  26.     EXTRN    linebuf:BYTE        ;line buffer
  27.     EXTRN    lastchar:WORD
  28.     EXTRN    dirstk_error:BYTE
  29.     EXTRN    resident:BYTE
  30.     EXTRN    abort_install:PROC
  31.     EXTRN    abort_processing:PROC
  32.     EXTRN    skip_whitespace:PROC
  33.     EXTRN    skip_nonwhite:PROC
  34.     EXTRN    tolower:PROC
  35.  
  36. dir_stk    $string_stack   <>        ;Buffer descriptors
  37. enable_dircmds    db    1        ;If 1, enables directory commands
  38. ;                     even if caller is not DOS
  39.  
  40. DGROUP    GROUP    CSEG
  41.     ASSUME    CS:DGROUP,DS:DGROUP,ES:DGROUP,SS:DGROUP
  42.  
  43.  
  44. ;+
  45. ; FUNCTION : dirs_init
  46. ;
  47. ; Initializes the various data structures associated with the
  48. ; directory stack buffer. CALLER MUST ENSURE PASSED ADDRESSES ARE VALID
  49. ; AND BUFFER IS LARGE ENOUGH.
  50. ;
  51. ; Parameters:
  52. ;    AX     - length of buffer in bytes
  53. ;    BX    - address of buffer
  54. ;
  55. ; Returns:
  56. ;    AX =    0 if no errors
  57. ;        -1 otherwise
  58. ; Registers destroyed : BX
  59. ;-
  60. dirs_init proc    near
  61.     push    bx
  62.     mov    bx,offset DGROUP:dir_stk ;bx := address of buffer descriptors
  63.     xchg    ax,cx            ;CX = buffer size
  64.     pop    ax            ;AX = Buffer address
  65.                     ;BX points to appropriate descriptor
  66.     call    near ptr strstk_init    ;Initialize buffer and descriptor
  67.     ret
  68. dirs_init    endp
  69.  
  70.  
  71. ;+
  72. ; FUNCTION: execute_rstdir
  73. ;
  74. ;    Called to reset the directory stack.
  75. ;
  76. ; Parameters:
  77. ;    None.
  78. ;-
  79. execute_rstdir proc near
  80.     mov    bx,offset DGROUP:dir_stk
  81.     call    near ptr strstk_reset
  82.     ret
  83. execute_rstdir endp
  84.  
  85. ;+
  86. ; FUNCTION : dir_push
  87. ;
  88. ;    Called to push a drive and path onto the directory stack. The
  89. ;    string must end in a 0 byte.
  90. ;
  91. ; Parameters:
  92. ;    DX    ->string to push
  93. ;
  94. ; Returns:
  95. ;    CF    = 1 if errors
  96. ;          0 no errors
  97. ;
  98. ; Register(s) destroyed:
  99. ;    AX,BX,CX,DX
  100. ;-
  101. dir_push proc    near
  102.     @save    di
  103.     mov    di,dx                ;di->string
  104.     mov    cx,0ffffh
  105.     xor    al,al
  106.     repne    scasb
  107.     mov    ax,cx
  108.     not    ax                ;AX<-length of string
  109. ;                         including null terminator
  110.     mov    bx,offset DGROUP:dir_stk
  111.     xor    cx,cx                ;Don't force push
  112.     call    near ptr strstk_push        ;Params AX,BX,CX,DX
  113.     ; strstk_push sets/resets CF
  114.     @restore
  115.     ret
  116. dir_push endp
  117.  
  118. ;+
  119. ; FUNCTION : abort_dir_op
  120. ;
  121. ;    Called to abort a directory stack operation. Action taken
  122. ;    depends on whether the program is already resident or is being
  123. ;    installed. This routine does NOT return to caller.
  124. ;
  125. ; Parameters:
  126. ;    AX    = code to pass to abort_processing
  127. ;
  128. ; Returns:
  129. ;    Nothing.
  130. ; Register(s) destroyed:
  131. ;-
  132. abort_dir_op proc near
  133.     mov    dx,offset DGROUP:abort_processing
  134.     cmp    resident,0
  135.     jne    @abort_dir_op_90        ;Jump if resident
  136.     @DispStr dirstk_error
  137.     mov    dx,offset DGROUP:abort_install
  138. @abort_dir_op_90:
  139.     jmp    dx
  140. abort_dir_op endp
  141.  
  142.  
  143.  
  144.  
  145. ;+
  146. ; FUNCTION : check_dircmd_allowed
  147. ;
  148. ;    Makes sure DOS is the caller or directory commands have been
  149. ;    enabled for all applications and returns. Else aborts.
  150. ;
  151. ; Parameters:
  152. ;    None.
  153. ;
  154. ; Returns:
  155. ;    Nothing.
  156. ; Register(s) destroyed:
  157. ;     AX
  158. ;-
  159. check_dircmd_allowed proc near
  160.     cmp    enable_dircmds,1
  161.     je    @check_dircmd_allowed_99
  162.     mov    ax,E_DIRSTK_DOS            ;Assume error
  163.     cmp    in_appl,1            ;In application ?
  164.     je    abort_dir_op            ;Yes, abort
  165. @check_dircmd_allowed_99:                    ;Else return
  166.     ret
  167. check_dircmd_allowed endp
  168.  
  169.  
  170. ;+
  171. ; FUNCTION : save_drv_path
  172. ;
  173. ;    Saves the current drive and path in the specified buffer in the
  174. ;    form `D:\dir1....' where the current drive letter. The buffer
  175. ;    MUST be long enough.
  176. ;
  177. ; Parameters:
  178. ;    AX    = address of save buffer
  179. ;
  180. ; Returns:
  181. ;    Nothing.
  182. ;
  183. ; Register(s) destroyed:
  184. ;    AX,DX
  185. ;-
  186. save_drv_path    proc near
  187.     @save    si,di
  188.     mov    di,ax                ;DI->save buffer
  189.     @GetDrv                    ;AL<-drive number
  190.     add    al,'a'                ;AL<-drive letter
  191.     stosb                    ;Remember current drive
  192.     mov    al,':'
  193.     stosb
  194.     mov    al,'\'
  195.     stosb
  196.     @GetDir di                ;Remember current path
  197.     @restore
  198.     ret
  199. save_drv_path    endp
  200.  
  201.  
  202.  
  203. ;+
  204. ; FUNCTION : change_drv_path
  205. ;
  206. ;    Changes the current drive and directory to the one specified.
  207. ;
  208. ; Parameters:
  209. ;    AX    ->path in the form `D:\dir1\dir2\...' terminated
  210. ;          with a 0 byte where D is the drive letter. Entire
  211. ;          path name need no be given. It is OK if the last
  212. ;          directory in the path is followed by a '\'.
  213. ;
  214. ; Returns:
  215. ;    CF    = 0 if current drive and directory succesfully changed,
  216. ;          1 if any errors (drive and path both unchanged)
  217. ; Register(s) destroyed:
  218. ;-
  219. change_drv_path proc near
  220.     @save    si,di
  221.     push    bp
  222.     mov    bp,sp
  223.     sub    sp,PATHBUF_SIZE
  224. cur_path    equ <byte ptr [bp-PATHBUF_SIZE]>
  225.     push    ax                ;Remember new path
  226.     lea    ax,cur_path            ;AX->current path save buf
  227.     call    near ptr save_drv_path        ;Save current disk/dir
  228.     pop    dx                ;DX->new path
  229.     mov    si,dx                ;SI->new path
  230.     mov    di,dx
  231.     xor    al,al                ;Search for terminator
  232.     mov    cx,0ffffh
  233.     repne    scasb                ;DI->byte after NULL
  234.     cmp    byte ptr [di-2],'\'        ;Extra '\' char ?
  235.     jne    @change_drv_path_10        ;No
  236.     ;If '\' at the end, make sure it is not of the form d:\ or just \
  237.     cmp    byte ptr [di-3],':'
  238.     je    @change_drv_path_10
  239.     dec    di
  240.     dec    di                ;DI->'\' character
  241.     cmp    di,dx                ;Solitary '\' ?
  242.     je    @change_drv_path_10        ;Yes
  243.     mov    [di],al                ;No, replace '\' with 0
  244. @change_drv_path_10:
  245.     @ChDir    dx
  246.     jnc    @change_drv_path_80        ;No error
  247. ;     Check if error was because drive was specified but not the path.
  248. ;    In this case, we should only change the drive.
  249.     cmp    byte ptr 2[si],0        ;third byte nust be null
  250.     jne    @change_drv_path_85        ;Nope
  251.     cmp    byte ptr 1[si],':'        ;Drive specified ?
  252.     jne    @change_drv_path_85        ;Nope
  253.     jmp    short @change_drv_path_82
  254. @change_drv_path_80:
  255.     cmp    byte ptr 1[si],':'        ;Drive spec ?
  256.     clc                    ;To indicate success
  257.     jne    @change_drv_path_99        ;No, all done
  258. @change_drv_path_82:
  259.     lodsb                    ;AL<-drive
  260.     call    near ptr tolower
  261.     sub    al,'a'                ;AL<-drive number
  262.     @SetDrv al                ;Change the drive
  263.     jnc    @change_drv_path_99        ;No error
  264. ;     Error, restore path, drive would not have been changed
  265. @change_drv_path_85:
  266.     lea    dx,cur_path
  267.     @ChDir    dx
  268.     stc                    ;Indicate error to caller
  269. @change_drv_path_99:
  270.     mov    sp,bp
  271.     pop    bp
  272.     @restore
  273.     ret
  274. change_drv_path endp
  275.  
  276.  
  277.  
  278. ;+
  279. ; FUNCTION : execute_popd
  280. ;
  281. ;    Pops the topmost element off the directory stack and makes it
  282. ;    the current drive/directory.
  283. ;
  284. ; Parameters:
  285. ;    None.
  286. ;
  287. ; Returns:
  288. ;    Nothing.
  289. ;
  290. ; Register(s) destroyed:
  291. ;    AX,BX,CX,DX
  292. ;-
  293. execute_popd proc near
  294.     call    near ptr check_dircmd_allowed
  295.     @save    si,di
  296.     push    bp
  297.     mov    bp,sp
  298.     sub    sp,PATHBUF_SIZE
  299. topdir    equ    PATHBUF_SIZE
  300.     mov    bx,offset DGROUP:dir_stk    ;BX->dir stack descriptor
  301.     call    near ptr strstk_settop
  302.     lea    ax,[bp-topdir]
  303.     mov    cx,PATHBUF_SIZE
  304.     call    near ptr strstk_copy        ;Get top of stack
  305. ;                         String is terminated
  306. ;                         by a 0 byte
  307.     jc    @execute_popd_90
  308.     or    ax,ax                ;Empty stack ?
  309.     jz    @execute_popd_90        ;Yes, error
  310.     lea    ax,[bp-topdir]            ;AX->new path
  311.     call    near ptr change_drv_path    ;Change drive and path
  312.     jc    @execute_popd_90
  313.     call    near ptr strstk_kill        ;Delete top of stack
  314.     mov    sp,bp
  315.     pop    bp
  316.     @restore
  317. ; Klugery - return a zero length string to DOS in order to set prompt properly.
  318.     mov    lastchar,offset DGROUP:linebuf
  319.     mov    user_command,1            ;indicate line to be
  320. ;                         returned to DOS
  321.     ret
  322.  
  323. @execute_popd_90:
  324.     mov    ax,E_DIRSTK_EMPTY
  325.     jmp    near ptr abort_dir_op
  326. execute_popd    endp
  327.  
  328.  
  329.  
  330. ;+
  331. ; FUNCTION : execute_pushd
  332. ;
  333. ;    If a parameter is given, pushes current directory/disk onto the
  334. ;    dir stack and changes to the parameter. If no parameter,
  335. ;    exchange the top of directory stack with current disk-directory.
  336. ;
  337. ; Parameters:
  338. ;    SI    -> first char in linebuf following this command
  339. ;    CX    = remaining num chars in line
  340. ;
  341. ; Returns:
  342. ;    Nothing.
  343. ;
  344. ; Register(s) destroyed:
  345. ;    AX,BX,CX,DX
  346. ;-
  347. execute_pushd    proc    near
  348.     @save    si,di
  349.     push    bp
  350.     mov    bp,sp
  351.     sub    sp,2*PATHBUF_SIZE
  352. cur_path    equ <byte ptr [bp-PATHBUF_SIZE]>
  353. new_path    equ <byte ptr [bp-(2*PATHBUF_SIZE)]>
  354.     call    near ptr check_dircmd_allowed
  355. ;                         Will return only if so
  356.     push    cx                ;Save line length
  357.     lea    ax,cur_path
  358.     call    near ptr save_drv_path        ;Save current drive and path
  359.  
  360.     pop    cx                ;CX<-restored line length
  361.     call    near ptr skip_whitespace
  362.     ; SI->first non blank, CX<-num remaining chars
  363.     jcxz    @execute_pushd_50        ;Exchange directory
  364. ;                         with top of stack
  365.     push    si                ;SI->path to change to
  366.     call    near ptr skip_nonwhite
  367.     ; SI->first non-blank
  368.     mov    byte ptr [si],0            ;Terminating 0 byte
  369. ;    We are guaranteed place for a 0 because of the dummy byte after linebuf
  370.     pop    ax                ;AX->dir to change to
  371.     call    near ptr change_drv_path    ;Change path and drive
  372.     jc    @execute_pushd_32        ;Error
  373. @execute_pushd_25:
  374.     lea    dx,cur_path
  375.     call    near ptr dir_push        ;Push onto stack
  376.     jnc    @execute_pushd_100        ;No error
  377. @execute_pushd_30:
  378. ; Error. Restore original directory and display error message.
  379.     lea    ax,cur_path
  380.     call    near ptr change_drv_path
  381. @execute_pushd_32:
  382.     mov    ax,E_DIRSTK
  383.     jmp    abort_dir_op
  384.  
  385. @execute_pushd_50:
  386. ; Exhange current directory with the directory at the top of the stack
  387.     mov    bx,offset DGROUP:dir_stk    ;BX->dir stack descriptor
  388.     call    near ptr strstk_settop
  389.     lea    ax,new_path
  390.     mov    cx,PATHBUF_SIZE
  391.     call    near ptr strstk_copy        ;Get top of stack
  392. ;                         String is terminated
  393. ;                         by a 0 byte
  394.     jnc    @execute_pushd_60
  395. @execute_pushd_55:
  396.     lea    ax,cur_path
  397.     call    near ptr change_drv_path
  398.     mov    ax,E_DIRSTK_EMPTY
  399.     jmp    abort_dir_op
  400. @execute_pushd_60:
  401.     or    ax,ax                ;Empty stack ?
  402.     jz    @execute_pushd_55        ;Yes, error
  403.     lea    ax,new_path            ;AX->new path
  404.     call    near ptr change_drv_path    ;Change drive and path
  405.     jc    @execute_pushd_30
  406.     call    near ptr strstk_kill        ;Delete top of stack
  407.     lea    dx,cur_path
  408.     call    near ptr dir_push
  409.     jnc    @execute_pushd_100            ;All set
  410. ;    Error. Restore original top of stack
  411.     lea    dx,new_path
  412.     call    near ptr dir_push        ;Push must succeed
  413.     jmp    short @execute_pushd_30
  414.  
  415. @execute_pushd_100:
  416.     mov    sp,bp
  417.     pop    bp
  418.     @restore
  419. ; Klugery - return a zero length string to DOS in order to set prompt properly.
  420.     mov    lastchar,offset DGROUP:linebuf
  421.     mov    user_command,1            ;indicate line to be
  422. ;                         returned to DOS
  423.     ret
  424. execute_pushd    endp
  425.  
  426.  
  427.  
  428.  
  429. ;+
  430. ; FUNCTION : execute_chd
  431. ;
  432. ;    Changes to the disk and directory specified as parameter.
  433. ;
  434. ; Parameters:
  435. ;    SI    -> first char in linebuf following this command
  436. ;    CX    = remaining num chars in line
  437. ;
  438. ; Returns:
  439. ;    Nothing.
  440. ;
  441. ; Register(s) destroyed:
  442. ;    AX,BX,CX,DX
  443. ;-
  444. execute_chd    proc    near
  445.     @save    si,di
  446.     push    bp
  447.     mov    bp,sp
  448.     sub    sp,PATHBUF_SIZE
  449. new_path    equ <byte ptr [bp-PATHBUF_SIZE]>
  450.     call    near ptr check_dircmd_allowed
  451. ;                         Will return only if so
  452.     push    cx                ;Save line length
  453.     call    near ptr skip_whitespace
  454.     ; SI->first non blank, CX<-num remaining chars
  455.     jcxz    @execute_chd_100        ;No args
  456. ;                         with top of stack
  457.     push    si                ;SI->path to change to
  458.     call    near ptr skip_nonwhite
  459.     ; SI->first non-blank
  460.     mov    byte ptr [si],0            ;Terminating 0 byte
  461. ;    We are guaranteed place for a 0 because of the dummy byte after linebuf
  462.     pop    ax                ;AX->dir to change to
  463.     call    near ptr change_drv_path    ;Change path and drive
  464.     jnc    @execute_chd_100            ;No error
  465.     mov    ax,E_DIRSTK
  466.     jmp    abort_dir_op
  467.  
  468. @execute_chd_100:
  469.     mov    sp,bp
  470.     pop    bp
  471.     @restore
  472. ; Klugery - return a zero length string to DOS in order to set prompt properly.
  473.     mov    lastchar,offset DGROUP:linebuf
  474.     mov    user_command,1            ;indicate line to be
  475. ;                         returned to DOS
  476.     ret
  477. execute_chd endp
  478.  
  479.  
  480.  
  481.  
  482.  
  483. CSEG    ENDS
  484.  
  485.     END