home *** CD-ROM | disk | FTP | other *** search
/ Simtel MSDOS 1992 June / SIMTEL_0692.cdr / msdos / dirutl / newchdir.arc / C.ASM next >
Assembly Source File  |  1988-11-19  |  9KB  |  385 lines

  1.  
  2. page 60,132
  3.  
  4. ; Copyright (C) 1988  Mark Adler  Pasadena, CA
  5. ; All rights reserved.
  6.  
  7.  title C -- enhanced change directory command
  8.  name C
  9.  
  10. comment #
  11.  
  12. C.COM -
  13.  
  14. This program is an enhanced change directory (CD) command.  It is used
  15. like CD, except that abbreviations of subdirectory names are accepted.
  16. Only that part of each subdirectory name that uniquely distinguishes it
  17. from the others is necessary.  For example, suppose the current drive
  18. has this directory tree:
  19.  
  20.  \ ─┬─ DOS
  21.     ├─ BIN ─┬─ TURBOC
  22.     │       ├─ MASM
  23.     │       └─ MATHCAD
  24.     └─ USR ─┬─ UTIL
  25.             └─ BBS ─┬─ COMPUSRV
  26.                     └─ BULL
  27.  
  28. Then the command:
  29.  
  30.         c \u\b\b
  31.  
  32. will make the current directory \USR\BBS\BULL.  The command:
  33.  
  34.         c \b\ma
  35.  
  36. will not change the directory, but instead give the response:
  37.  
  38.         \BIN\ma*.* is ambiguous---it matches: MASM,MATHCAD
  39.  
  40. Then the command:
  41.  
  42.         c \m\mat
  43.  
  44. will make the current directory \BIN\MATHCAD.  Whether changing a
  45. directory or not, C will display the current directory of the drive
  46. specified (or the current drive if none is specified).
  47.  
  48. Putting this program on a RAM disk and setting the PATH appropriately
  49. will make C as fast as resident commands (like CD).
  50.  
  51. #
  52.  
  53.  
  54. ;
  55. ; Program segment.
  56. ;
  57.  
  58. c segment
  59.  assume CS:c,DS:c,ES:c,SS:c
  60.  
  61.  
  62. ;
  63. ; Structure for BP data.
  64. bpdata struc
  65.  find db 21 dup (?)     ;Find first, next DTA.
  66.  fattr db ?             ;Attribute of file found.
  67.   dw 4 dup (?)          ;Time, date, size of file found.
  68.  fname db 13 dup (?)    ;Name of file found
  69.  tname db 13 dup (?)    ;Temporary save for name.
  70.  drv db ?               ;Drive specified or current drive.
  71.   db ?                  ;(just to make it even)
  72. bpdata ends
  73.  
  74.  
  75. ;
  76. ; Command line.
  77.  org 80h
  78. cmd label byte
  79.  
  80.  
  81. ;
  82. ; Start of .COM code.
  83.  org 100h
  84. start:
  85.   jmp cpyrt
  86.    db 13,'Enhanced chdir version 1.0  '
  87.    db 'Copyright (C) 1988  Mark Adler',13,10
  88.    db 'All rights reserved.',13,10
  89.    db 13,10
  90.    db 'Use this command like CD, except that you do not have to use the'
  91.    db 13,10
  92.    db 'whole name for each subdirectory.  Only the part that uniquely'
  93.    db 13,10
  94.    db 'identifies it from the others is needed.'
  95.    db 13,10,'Z'-64
  96.  cpyrt:
  97.  ;
  98.  
  99.         ; set up.
  100.   cld                   ;Assumed to hold throughout this program.
  101.   sub SP,size bpdata    ;Allocate space for BP data.
  102.   mov BP,SP
  103.   lea DX,[BP].find      ;Set DTA to the find area.
  104.   mov AH,1Ah
  105.   int 21h
  106.  
  107.         ; get current drive and total drives.
  108.   mov AH,19h
  109.   int 21h
  110.   mov DL,AL             ;Save drive for select disk.
  111.   inc AX
  112.   mov [BP].drv,AL
  113.   mov AH,0Eh            ;Set current drive to current drive, just to get
  114.   int 21h               ; the total number of drives.
  115.   mov CL,AL             ;Save total.
  116.  
  117.         ; set up command line, point SI to first non-blank.
  118.   mov SI,offset cmd
  119.   lodsb                 ;Get length and terminate line with a 0.
  120.   cbw
  121.   mov BX,AX
  122.   mov byte ptr [SI+BX],0
  123.  isb:
  124.    cmp byte ptr [SI],' '
  125.    jne nonb
  126.    inc SI
  127.    jmp short isb
  128.  nonb:
  129.  
  130.         ; see if anything on command line.
  131.   cmp byte ptr [SI],0
  132.   jne args
  133.    jmp showdir          ;If not, go show the current directory.
  134.  args:
  135.  
  136.         ; initialize path, pointer to path.
  137.   mov DI,offset path
  138.   mov byte ptr [DI],0
  139.  
  140.         ; Pull out drive, if specified.
  141.   cmp byte ptr [SI+1],':'
  142.   jne nodrv
  143.    mov AL,[SI]
  144.    and AL,5Fh           ;Convert lower to upper case.
  145.    sub AL,'A'-1
  146.    mov DX,offset err1
  147.    cmp AL,1             ;Check bounds.
  148.    jb erra
  149.    cmp AL,CL            ;Must be less than or equal to total drives.
  150.    jbe dok
  151.   erra:
  152.     jmp errx
  153.   dok:
  154.    mov [BP].drv,AL
  155.    movsw                ;Copy drive letter and colon to path.
  156.  nodrv:
  157.  
  158.         ; see if more than just a drive.
  159.   cmp byte ptr [SI],0
  160.   jne ismore
  161.    jmp showdir          ;If not, just show directory.
  162.  ismore:
  163.  
  164.         ; for each part of specified path, find a match.
  165.  nxtlvl:
  166.  
  167.         ; pull off next part of path.
  168.    mov BX,DI            ;Level pointer is now BX.
  169.    mov AH,0             ;Initialize dot count.
  170.    lodsb                ;Get first character.
  171.   pullp:
  172.     cmp AL,'.'          ;See if it's a dot.
  173.     jne nodot
  174.      inc AH             ;If so, increment dot count.
  175.    nodot:
  176.     stosb               ;Store character.
  177.     lodsb               ;Get next character.
  178.     cmp AL,'\'          ;See if path delimiter or end of string.
  179.     je pulend
  180.     cmp AL,'/'
  181.     je pulend
  182.     cmp AL,0
  183.     jne pullp           ;If not, copy more.
  184.   pulend:
  185.    dec SI               ;Point back to character that ended it.
  186.  
  187.         ; point level past delimiter, see if name there to match.
  188.    cmp byte ptr [BX],'\'
  189.    je skipdel
  190.    cmp byte ptr [BX],'/'
  191.    jne noskip
  192.   skipdel:
  193.     inc BX
  194.     cmp BX,DI           ;See if anything past the delimiter.
  195.     jne noskip
  196.      jmp cont           ;If no more, then nothing to match.
  197.   noskip:
  198.  
  199.         ; see if it's "." or "..".
  200.    mov DX,DI            ;See if the name is all dots.
  201.    sub DX,BX
  202.    cmp DL,AH
  203.    jne notdots
  204.    cmp AH,3             ;See if it's one or two dots.
  205.    jb exact             ;It is all dots---consider it already matched.
  206.   notdots:
  207.  
  208.         ; see if it's an exact match before searching.
  209.    push AX              ;Save dot count.
  210.    mov byte ptr [DI],0  ;Terminate path.
  211.    mov DX,offset path   ;Do a find first.
  212.    mov CX,17h           ;Find any kind of file except labels.
  213.    mov AH,4Eh
  214.    int 21h
  215.    pop AX               ;Restore dot count.
  216.    jb notexact
  217.    test [BP].fattr,10h  ;See if it's a directory.
  218.    jz notexact
  219.   exact:
  220.     jmp cont            ;Exact match---do next part of argument.
  221.   notexact:
  222.  
  223.         ; append * or *.* for search.
  224.    test AH,AH           ;See if any dots in name.
  225.    mov AX,'.*'
  226.    jnz hasext           ;If so, then name has an extension.
  227.     stosw               ;If no extension, append "*.".
  228.   hasext:
  229.    mov AH,0             ;Append "*",0.
  230.    stosw
  231.  
  232.         ; look for a match.
  233.    mov DX,offset path   ;Do a find first.
  234.    mov CX,17h
  235.    mov AH,4Eh
  236.    int 21h
  237.    jb nomatch
  238.   tildir:               ;Search until a directory matches the name.
  239.     test [BP].fattr,10h
  240.     jnz ismatch
  241.     mov AH,4Fh          ;Do a find next.
  242.     int 21h
  243.     jnb tildir
  244.   nomatch:              ;Couldn't find one.
  245.    mov SI,offset err2
  246.    call puts
  247.    mov SI,offset path
  248.    call puts
  249.    mov DX,offset crlf
  250.    jmp errx
  251.  
  252.         ; got a match, look for a second match.
  253.  ismatch:
  254.    mov DX,SI            ;Save argument pointer.
  255.    lea SI,[BP].fname    ;Save the name that was found.
  256.    lea DI,[BP].tname
  257.    mov CX,13
  258.    rep movsb
  259.    mov SI,DX            ;Restore argument pointer.
  260.   fndnxt:
  261.     mov AH,4Fh          ;Do a find next.
  262.     int 21h
  263.     jb no2nd
  264.     test [BP].fattr,10h
  265.     jz fndnxt
  266.  
  267.         ; got a second match---display the first two and all other
  268.         ; matches and return with an error.
  269.    mov SI,offset path
  270.    call puts
  271.    mov SI,offset err3
  272.    call puts
  273.    lea SI,[BP].tname    ;Show first match.
  274.    call puts
  275.   amblp:
  276.     mov DL,','          ;Show next match.
  277.     mov AH,2
  278.     int 21h
  279.     lea SI,[BP].fname
  280.     call puts
  281.    fndlp:               ;Look for another match.
  282.      mov AH,4Fh         ;Do a find next.
  283.      int 21h
  284.      jb ambfin
  285.      test [BP].fattr,10h
  286.      jz fndlp
  287.     jmp short amblp     ;Found another match, show it.
  288.   ambfin:
  289.    mov DX,offset crlf   ;Return with error.
  290.    jmp short errx
  291.  
  292.         ; no second match, add new match to name.
  293.  no2nd:
  294.    mov DX,SI            ;Save argument pointer.
  295.    lea SI,[BP].tname    ;Copy matched name to current level in path.
  296.    mov DI,BX
  297.   cpylp:
  298.     movsb
  299.     cmp byte ptr [SI],0
  300.     jne cpylp
  301.    mov SI,DX            ;Restore argument pointer.
  302.  
  303.         ; loop on parts of specified path (level pointer assumed in DI).
  304.   cont:
  305.    cmp byte ptr [SI],0  ;See if end of argument.
  306.    je argend
  307.    cmp byte ptr [SI],' '
  308.    je argend
  309.    jmp nxtlvl           ;More---process it.
  310.  argend:
  311.  
  312.         ; change to new path.
  313.   mov byte ptr [DI],0   ;Terminate path.
  314.   mov DX,offset path    ;Change directory.
  315.   mov AH,3Bh
  316.   int 21h
  317.   mov DX,offset err4
  318.   jb errx
  319.  
  320.         ; show the current directory.
  321. showdir:
  322.   mov DL,[BP].drv       ;Get current directory.
  323.   mov SI,offset cmd     ;Put it over the command line.
  324.   mov AH,47h
  325.   int 21h
  326.   mov DX,offset err5
  327.   jb errx
  328.   mov DL,[BP].drv       ;Show drive.
  329.   add DL,'A'-1
  330.   mov AH,2
  331.   int 21h
  332.   mov DL,':'
  333.   int 21h
  334.   mov DL,'\'
  335.   int 21h
  336.   mov SI,offset cmd     ;Show current directory.
  337.   call puts
  338.   mov SI,offset crlf
  339.   call puts
  340.   int 20h               ;Done.
  341.  
  342.  
  343. errx:
  344.   mov SI,DX
  345.   call puts
  346.   mov AX,4C01h          ;Terminate with error.
  347.   int 21h
  348.  
  349.  
  350. puts proc near
  351.  ;
  352.  ; Send string at SI to stdout.
  353.  ;
  354.  putslp:
  355.    lodsb
  356.    test AL,AL
  357.    jz putsfin
  358.    mov DL,AL
  359.    mov AH,2
  360.    int 21h
  361.    jmp short putslp
  362.  putsfin:
  363.   ret
  364. puts endp
  365.  
  366.  
  367. ;
  368. ; Initialized data -
  369. err1 db 'Invalid drive specification',13,10,0
  370. err2 db 'No such directory ',0
  371. err3 db ' is ambiguous---it matches: ',0
  372. err4 db 'Invalid directory',13,10,0
  373. err5 db 'Unable to determine the current directory'
  374. crlf db 13,10,0
  375.  
  376.  
  377. ;
  378. ; Uninitialized data -
  379. path label byte
  380.  
  381.  
  382. c ends
  383.  
  384. end start
  385.