home *** CD-ROM | disk | FTP | other *** search
/ Phoenix CD 2.0 / Phoenix_CD.cdr / 24b / lut191.zip / LUT191.ASM
Assembly Source File  |  1989-03-20  |  21KB  |  1,014 lines

  1.     Page    80,132
  2.     Title    'LUT - List LBR Directory'
  3.     Comment    |
  4.  
  5. LUT Command
  6. -----------
  7.  
  8. Purpose:   Displays the    contents of one    or more    library    (LBR) files
  9.        created by the LU or    LAR utility.
  10.  
  11. Format:       LUT    [d:][path]filename[.ext]
  12.  
  13. Remarks:   If no operands are supplied,    all files with an
  14.        extension of    LBR in the current path    are listed.
  15.        Global filename characters *    and ? are allowed in
  16.        the filename    and extension.
  17.  
  18. Examples:
  19.     1) List    directory of all LBR files on drive B
  20.         LUT B:
  21.  
  22.     2) List    directories of all LBR files on    current    drive
  23.         LUT
  24.  
  25.     3) List    all LBR    directories of filenames beginning with    XYZ
  26.         LUT XYZ*.LBR -or- LUT XYZ?????.LBR
  27.  
  28.     4) List    all LBR    directories in subdirectory called ABC
  29.         LUT \ABC
  30.  
  31. Notes:       Written for the IBM PC using    DOS 2.0    or later.
  32.        Copyright 1984 Vernon Buerg.    For public domain use.
  33.  
  34.     Version 1.7, Aug 8, 1984
  35.     Version 1.8, Aug 15,1984
  36.                 sorted directory list
  37.                 display member CRC and Index pointers
  38.                 calculate directory CRC
  39.     Version 1.81, Aug 29, 1984
  40.                 added CP/M LU86 date/time formatting
  41.     Version 1.82, Sep 4, 1984
  42.                 remove CRC display, use D_Pad
  43.     Version 1.83, Sep 25, 1984
  44.                 correct command operands
  45.     Version 1.90, Nov 10, 1984
  46.                 default extension to LBR
  47.     Version 1.91, Feb 9, 1985
  48.                 correct CHDIR problem
  49. ----------|
  50.  
  51.     Page
  52. DirNtry    Struc                ;LU/LAR    directory entries
  53. D_Stat    Db    0            ;File status
  54. D_File    Db    8 Dup (' ')        ;File name (FCB    format)
  55. D_Ext    Db    3 Dup (' ')        ; and extension
  56. D_Ptr    Dw    0            ;Offset    to data    (mod 128)
  57. D_Len    Dw    0            ;Length, 128-byte sectors
  58.  
  59. D_CRC    Db    2 Dup (0)        ;CRC check bytes \
  60. D_Cdate    Db    2 Dup (0)        ;Create date      \
  61. D_Udate    Db    2 Dup (0)        ;Update date       LU86 format
  62. D_Ctime    Db    2 Dup (0)        ;Create time      /
  63. D_Utime    Db    2 Dup (0)        ;Update time     /
  64. D_Pad    Db    6 Dup (0)        ;Pad bytes in last block
  65. DirNtry    Ends
  66.  
  67. Active    Equ    0
  68. Deleted    Equ    254
  69. Unused    Equ    255
  70. Dir_Len    Equ    Size DirNtry
  71.  
  72. CR    Equ    13
  73. LF    Equ    10
  74. Stopper    Equ    255
  75.  
  76. Dater    Record    Yr:7,Mo:4,Dy:5
  77. Timer    Record    HH:5,MM:6,XX:5
  78.  
  79.  
  80. Cseg    Segment    Public Para 'CODE'
  81.     Assume    CS:Cseg,DS:Cseg,ES:Cseg
  82.     Org    100h
  83.  
  84. Lut    Proc    Far
  85.     Lea    SP,Stackx        ;Use local stack
  86.     Push    DS            ;Standard entry
  87.     Sub    AX,AX            ; for DOS return
  88.     Push    AX
  89.     Mov    Stk_Top,SP        ;Save for exit
  90.     Jmp    Ver
  91.     Page
  92. ;
  93. ;    Constants and work areas
  94.  
  95. Mode    Db    0            ;New or    old format
  96. ;       01 = ***DIR format    02 = CRC included
  97. ;       04 = LU86 stamps    08 = CRC invalid
  98.  
  99. TotBlk    Dw    0            ;Total blocks used
  100. NumDel    Db    0            ;Deleted entries
  101. ByteDel    Dw    0            ;Blocks    deleted
  102. Entries    Dw    0            ;Entries in dir
  103. LenDir    Dw    0            ;Total directory size
  104.  
  105. A_Buf    Dw    Offset DirBuf        ;Offset    to current entry
  106. Handle    Dw    0            ;File handle from open
  107. CurDisk    Db    255            ;Current disk
  108. Stk_Top    Dw    0            ;Stack ptr upon entry
  109.  
  110. SecSize    Dw    128            ;Logical sector    size
  111. NumActv    Db    1            ;Active    entries
  112.  
  113. FilePtr    Dw    Offset FileNm        ;Offset to filename part
  114. Filend    Dw    Offset FileNm        ; next char in file name
  115. Default    Db    '*.LBR'            ;Default criteria
  116. Zero    Dw    0               ; with ASCIIZ stopper
  117.  
  118. DirKey    Db    '********DIR'        ;In new    format libs
  119.  
  120. Heading    Db    CR,LF,LF
  121.     Db    '=== Library   '
  122. LbrName    Db    13 Dup (0)
  123. Blanks    Db    11 Dup (' ')
  124. LuDate    Db    10 Dup (' ')
  125. LuTime    Db    8 Dup (' '),Stopper
  126.  
  127. Header    Db    CR,LF,LF,'  Filename Ext   Bytes   Index  '
  128. Headern    Db    '  --- Created --- '
  129. Headerh    Db    '  --- Updated --- ',Stopper
  130.  
  131. Bmsg    Db    CR,LF,LF
  132. TotByte    Db    '      ',' bytes used;'
  133.  
  134. Dmsg    Equ    This Byte
  135. NumDir    Db    '      ',' alloc entries;'
  136. TotActv    Db    '      ',' active;'
  137. TotDel    Db    '      ',' deleted'
  138. Dmsg_nd    Db    Stopper            ; if none deleted
  139. DelByte    Db    '      ',' bytes',Stopper
  140.  
  141. Line    Db    CR,LF,'  '        ;DETAIL    print line
  142. Member    Db    'filename ext','  '
  143. NumByte    Db    8 Dup (32)
  144. Index    Db    8 Dup (32)
  145. L_End    Db    ' '            ; end of line if no stamps
  146. C_Date    Db    'mm/dd/yy '
  147. C_Time    Db    'hh:mm:ss'
  148. C_End    Db    ' '            ; if no update stamp
  149. U_Date    Db    'mm/dd/yy '
  150. U_Time    Db    'hh:mm:ss',Stopper
  151.  
  152. Msg1    Db    CR,LF,'No files found ',Stopper
  153. BadCRC    Db    CR,LF,'Dir CRC invalid',7,CR,LF,Stopper
  154. Msg3    Db    CR,LF,'I/O error',CR,LF,Stopper
  155. Msg6    Db    CR,LF,LF,'Invalid LBR format: ',Stopper
  156. Alocmsg    Db    CR,LF,'Not enough memory',Stopper
  157. Sorry    Db    CR,LF,'PC DOS Version 2.x required',Stopper
  158. Version    Db    'LUT - Version 1.91 - V.Buerg',Stopper
  159.     Page
  160. ;
  161. ;    Display and check versions
  162.  
  163. Ver:    Mov    DX,Offset Version    ;Display program name
  164.     Call    PrintS
  165.     Mov    AH,30h            ;Check DOS version
  166.     Int    21h
  167.     Cmp    AL,2
  168.     Jae    Alloc
  169.     Mov    DX,Offset Sorry
  170.     Jmp    Errors
  171.  
  172. ;    Allocate Directory Buffer
  173.  
  174. Alloc:    Mov    BX,Paras        ;Shrink    memory
  175.     Mov    AH,4Ah          ; to see if have engouh memory
  176.     Int    21h
  177.     Jnc    GetDta
  178.     Mov    DX,Offset Alocmsg
  179.     Jmp    Errors
  180.  
  181. GetDta:    Mov    DX,Offset DTA        ;Establish a DTA
  182.     Mov    Byte Ptr LstPath,255
  183.     Mov    AH,1Ah
  184.     Int    21h
  185.  
  186.     Call    GetParm            ;Get command parameters
  187.  
  188.     Mov    DX,FilePtr        ;Find first matching entry
  189.     Sub    CX,CX
  190.     Mov    AH,4Eh
  191.     Int    21h
  192.     Jc    Error4
  193.  
  194. Found:    Or    AL,AL            ;Any found?
  195.     Jnz    Done            ; no, all done
  196.  
  197.     Call    ListDir            ; yes, display it
  198.  
  199.     Mov    AH,4Fh            ;Find next entry
  200.     Int    21h
  201.     Jmp    Short Found
  202.     Page
  203. ;
  204. ;    Exits and error routines
  205.  
  206. Error4:    Mov    DX,Offset Msg1        ;Say NO    FILE(S) FOUND
  207.     Call    PrintS
  208.     Mov    DX,FilePtr        ; with filename
  209.  
  210. Errors:    Mov    AX,CS            ;Insure DS
  211.     Mov    DS,AX
  212.     Mov    SP,Stk_Top        ;Insure stack
  213.     Call    PrintS            ;Error message
  214.  
  215. Done:    Cmp    Byte Ptr LstPath,255    ; Was path changed?
  216.     Je    Done2
  217. Done1:    Mov    AH,3Bh            ; Restore target drive path
  218.     Mov    Byte Ptr OldPath,'\'
  219.     Mov    DX,Offset Oldpath
  220.     Int    21h
  221.  
  222. Done2:    Mov    AH,0Eh            ;Restore current disk
  223.     Mov    DL,CurDisk
  224.     Cmp    DL,255            ; was it changed?
  225.     Je    Exit
  226.     Int    21h
  227.  
  228. Exit:    Ret                ;Far return to DOS
  229.     Page
  230. ;
  231. ;    List directory for each    file
  232.  
  233. ListDir    Proc    Near
  234.  
  235.     Call    OpenLib            ;Access next library
  236.     Jc    Err1
  237.  
  238.     Call    ReadMst            ;Get master DIR entry
  239.     Jc    Err3
  240.  
  241.     Call    Verify            ;Validate master entry
  242.     Jc    Err6
  243.  
  244.     Call    ReadLib            ;Read remainder of directory
  245.     Jc    Err3
  246.  
  247.     Call    ChkCRC            ;Validate directory CRC
  248.  
  249.     Call    GetDate            ;Format file date/time
  250.  
  251.     Call    Sort            ;Sort into name order
  252.     Jmp    Short List1           ; and display directory
  253.  
  254. ;    Error messages
  255.  
  256. Err3:    Mov    DX,Offset Msg3        ;Say I/O error
  257.     Jmp    Short ErrMsg
  258.  
  259. Err1:    Mov    DX,Offset Msg1        ;Say OPEN FAILED
  260.     Jmp    Short ErrMsg
  261.  
  262. Err6:    Mov    DX,Offset Msg6        ;Say INVALID LBR FORMAT
  263.  
  264. ErrMsg:    Call    PrintS            ;Display error message
  265.     Mov    DX,FilePtr        ; with filename
  266.     Call    PrintS
  267.  
  268. Close:    Mov    BX,Handle        ;Close library
  269.     Or    BX,BX
  270.     Jz    Closed
  271.     Mov    AH,3Eh
  272.     Int    21h
  273. Closed:    Mov    Handle,0        ; indicate closed
  274.     Ret
  275.     Page
  276. ;    Display    the titles
  277.  
  278. List1:    Mov    SI,Offset DTA+30    ;Copy filename to heading
  279.     Mov    DI,Offset LbrName
  280.     Mov    CX,13
  281. List5:    Lodsb
  282.     Cmp    AL,0            ;End of name?
  283.     Je    List6
  284.     Stosb
  285.     Loop    List5
  286. List6:    Mov    AL,' '            ; pad with blanks
  287.     Rep    Stosb
  288.  
  289.     Mov    DX,Offset Heading    ;Display titles
  290.     Call    PrintS
  291.     Test    Mode,8            ;CRC okay?
  292.     Jz    List6c
  293.     Mov    DX,Offset BadCRC    ; no, say so
  294.     Call    PrintS
  295. List6c:    Mov    DX,Offset Header    ;Display headings
  296.     Call    PrintS
  297.  
  298. List7:    Mov    AX,Entries        ;Format number of DIR entries
  299.     Mov    DI,Offset NumDir
  300.     Call    Format
  301.  
  302. ;    Display each active entry
  303.  
  304. List10:    Mov    BX,A_Buf        ;Current buffer position
  305.     Cmp    [BX].D_Stat,Deleted    ;Entry deleted?
  306.     Jne    List12
  307.     Mov    AX,[BX].D_Len        ; yes, accumlate stats
  308.     Add    ByteDel,AX
  309.     Inc    NumDel
  310.     Jmp    List19
  311.  
  312. List12:    Cmp    [BX].D_Stat,Active    ;Is entry in use?
  313.     Je    List13            ; no, skip it
  314.     Jmp    List19
  315.  
  316. List13:    Inc    NumActv
  317.     Lea    SI,[BX].D_File        ;Display file name
  318.     Mov    DI,Offset Member
  319.     Mov    CX,8            ;Copy file name
  320.     Rep    Movsb
  321.     Inc    DI
  322.     Mov    CX,3            ; and extension
  323.     Rep    Movsb
  324.  
  325.     Mov    AX,[BX].D_Len        ;Number    of sectors
  326.     Add    TotBlk,AX
  327.  
  328.     Mul    SecSize            ;Calculate bytes
  329.     Test    Mode,1            ;DIR format?
  330.     Jnz    List13a
  331.     Test    Mode,6            ;LU86 format?
  332.     Jz    List13a
  333.     Mov    CL,Byte Ptr [BX].D_Pad
  334.     Sub    CH,CH
  335.     Sub    AX,CX
  336.     Sbb    DX,0
  337. List13a:Mov    DI,Offset NumByte
  338.     Call    Formatd            ; and format
  339.  
  340.     Mov    AX,[BX].D_Ptr        ;Format Index to data
  341.     Mov    DI,Offset Index
  342.     Call    Format
  343.  
  344.     Test    Mode,1            ;LU86 format?
  345.     Jnz    List17
  346.     Test    Mode,4            ; yes, has stamping?
  347.     Jz    List18            ; no, short lines
  348.  
  349.     Mov    DI,Offset C_Time    ;Format LU86 create stamp
  350.     Mov    DX,Word Ptr [BX].D_Ctime
  351.     Call    FixTime
  352.     Mov    DI,Offset C_Date
  353.     Mov    DX,Word Ptr [BX].D_Cdate
  354.     Call    CPM_Date
  355.  
  356.     Mov    DI,Offset U_Time    ;Format LU86 update stamp
  357.     Mov    DX,Word Ptr [BX].D_Utime
  358.     Or    DX,DX
  359.     Jnz    List14
  360.     Mov    DX,Word Ptr [BX].D_Ctime
  361. List14:    Call    FixTime
  362.     Mov    DI,Offset U_Date
  363.     Mov    DX,Word Ptr [BX].D_Udate
  364.     Or    DX,DX
  365.     Jnz    List15
  366.     Mov    DX,Word Ptr [BX].D_Cdate
  367. List15:    Call    CPM_Date
  368.     Jmp    Short List18
  369.  
  370. List17:    Mov    CX,8            ;New ASCII stamp format
  371.     Lea    SI,[BX].D_CRC
  372.     Mov    DI,Offset C_Date    ; copy date
  373.     Rep    Movsb
  374.     Mov    CX,8            ; and time
  375.     Lea    SI,[BX].D_Utime
  376.     Mov    DI,Offset C_Time
  377.     Rep    Movsb
  378.  
  379. List18:    Mov    DX,Offset Line        ;Display an entry
  380.     Call    PrintS
  381.  
  382. List19:    Dec    Entries            ;Dir count
  383.     Jz    List20
  384.     Add    BX,Dir_Len        ; for next entry
  385.     Mov    A_Buf,BX
  386.     Jmp    List10
  387.     Page
  388. ;
  389. ;    Display    totals
  390.  
  391. List20: Mov    AL,NumActv        ;Format    use count
  392.     Sub    AH,AH
  393.     Mov    DI,Offset TotActv
  394.     Call    Format
  395.  
  396. List22:    Mov    AL,NumDel        ;Format    deleted    count
  397.     Sub    AH,AH
  398.     Mov    DI,Offset TotDel
  399.     Call    Format
  400.  
  401. List23:    Mov    AX,TotBlk        ;Format total size in bytes
  402.     Mul    SecSize
  403.     Mov    DI,Offset TotByte
  404.     Call    Formatd
  405.  
  406. List24:    Cmp    NumDel,0        ;Any deleted?
  407.     Je    List25            ; no, just active totals
  408.     Mov    Dmsg_nd,''        ; yes, expand totals msg
  409.     Mov    AX,ByteDel
  410.     Mul    SecSize            ;Format    deleted    bytes
  411.     Mov    DI,Offset DelByte
  412.     Call    Formatd            ; from double word
  413.  
  414. List25:    Mov    DX,Offset Bmsg        ;Display Bmsg and Dmsg totals
  415.     Call    PrintS
  416.     Call    Close
  417.     Ret
  418.  
  419. ListDir    Endp
  420.     Page
  421. ;
  422. ;    Use next matching entry for Open
  423.  
  424. OpenLib    Proc    Near
  425.     Mov    SI,Offset DTA+30    ;Move name from    DTA
  426.     Mov    DI,FilePtr        ; for OPEN
  427.     Mov    CX,13
  428. Move:    Lodsb
  429.     Stosb
  430.     Cmp    AL,0            ; if end of name
  431.     Loopne    Move
  432.     Jcxz    Open
  433.     Rep    Stosb
  434.  
  435. Open:    Mov    DX,FilePtr        ;Open the library
  436.     Mov    AX,3D00h        ; for reading
  437.     Int    21h
  438.     Mov    Handle,AX
  439.     Ret
  440. OpenLib    Endp
  441.  
  442.  
  443. ReadMst    Proc    Near
  444.     Mov    BX,Handle        ;Read master directory entry
  445.     Mov    CX,32            ; first 32-byte record
  446.     Mov    DX,A_Buf
  447.     Mov    AH,3Fh
  448.     Int    21h
  449.     Jc    Error3
  450.     Cmp    AX,CX            ;Got all of it?
  451.     Jne    Error3
  452.     Ret
  453.  
  454. ReadLib:                ;Read remaining entries
  455.     Mov    BX,A_Buf
  456.     Mov    AX,Word Ptr [BX].D_Len    ;Sectors for direc.
  457.     Sub    DX,DX
  458.     Mov    TotBlk,DX
  459.     Mov    NumActv,DL        ;Reset counters
  460.     Mov    NumDel,DL
  461.  
  462.     Add    AX,AX            ;Calc number of entries
  463.     Add    AX,AX            ; four per sector
  464.     Mov    Entries,AX
  465.  
  466.     Dec    AX            ;Calc size remaining
  467.     Mov    CL,5            ; as 32-bytes each
  468.     Shl    AX,CL
  469.     Mov    CX,AX
  470.     Mov    LenDir,CX        ;Save length
  471.     Add    LenDir,Dir_Len        ; of entire directory
  472.  
  473.     Mov    BX,Handle        ;Read rest of directory
  474.     Mov    DX,A_Buf
  475.     Add    DX,Dir_Len
  476.     Mov    AH,3Fh
  477.     Int    21h
  478.     Jc    Error3
  479.     Cmp    AX,CX            ;Got all of it?
  480.     Jne    Error3
  481.     Ret
  482.  
  483. Error3:    Clc
  484.     Ret
  485. ReadMst    Endp
  486.     Page
  487. ;
  488. ;    Validate master directory entry
  489.  
  490. Verify    Proc    Near
  491.     Mov    BX,A_Buf
  492.     Sub    AX,AX
  493.     Cmp    Byte Ptr [BX].D_Stat,AL    ;Active    first entry?
  494.     Jne    NotLBR
  495.     Cmp    Word Ptr [BX].D_Ptr,AX    ;Valid index pointer?
  496.     Jne    NotLBR
  497.  
  498.     Mov    Mode,AL            ;Init LBR type and
  499.     Mov    AL,Stopper
  500.     Mov    Headern,AL        ; line lengths
  501.     Mov    Headerh,AL
  502.     Mov    L_End,AL
  503.     Mov    C_End,AL
  504.  
  505.     Mov    CX,11            ;Check name of blanks
  506.     Lea    SI,Word Ptr [BX].D_File
  507.     Mov    DI,Offset Blanks
  508.     Repe    Cmpsb
  509.     Jne    Ver4
  510.  
  511.     Cmp    Word Ptr [BX].D_CRC,CX    ;Any CRC?
  512.     Je    Ver2
  513.     Or    Mode,2            ; yes...
  514. Ver2:    Cmp    Word Ptr [BX].D_Ctime,CX
  515.     Je    Ver9            ;Any LU86 stamps?
  516.     Or    Mode,4            ; yes...
  517.     Mov    C_End,' '
  518.     Mov    Headerh,' '
  519.     Jmp    Short Ver8
  520.  
  521. Ver4:    Mov    CX,11            ;May be    new format
  522.     Lea    SI,Byte Ptr [BX].D_File
  523.     Mov    DI,Offset DirKey
  524.     Repe    Cmpsb
  525.     Jne    NotLBR
  526.     Mov    Mode,1            ;Indicate ***DIR format
  527. Ver8:    Mov    Headern,' '
  528.     Mov    L_End,' '
  529.  
  530. Ver9:   Clc                ;Return CD=0
  531.     Ret
  532.  
  533. NotLBR:    Stc                ;or CF=1 if not LBR
  534.     Ret
  535. Verify    Endp
  536.     Page
  537. ;
  538. ;    Check CRC for directory
  539.  
  540. ChkCRC    Proc    Near
  541.     And    Mode,0FFh-8        ;Clear error indication
  542.     Test    Mode,2            ;LU86 CRC included?
  543.     Jz    ChkCRC9            ; no, skip it
  544.     Mov    SI,A_Buf        ;Calculate directory CRC
  545.     Mov    BX,SI
  546.     Mov    CX,LenDir
  547.     Mov    DX,Word Ptr [BX].D_CRC    ;Save original CRC
  548.     Or    DX,DX            ; any used?
  549.     Jz    ChkCRC9            ; nope, skip check
  550.     Mov    Word Ptr [BX].D_CRC,0
  551.  
  552.     Call    GetCRC            ;CRC for directory block
  553.     Call    UpdCRC            ; and for end-of-block
  554.  
  555.     Mov    Word Ptr [BX].D_CRC,DX
  556.     Cmp    AX,DX            ;CRC correct?
  557.     Je    ChkCRC9
  558.     Or    Mode,8            ; no, indicate error
  559. ChkCRC9:Ret
  560. ChkCRC    Endp
  561.     Page
  562. ;
  563. ;    Calculate CRC for a block from CCIT polynomial
  564. ;
  565. ;    CRC = x^16 + x^12 + x^5 + 1
  566.  
  567. GetCRC    Proc    Near            ;SI points to data
  568.     Push    BX            ;CX contains length
  569.     Push    DX
  570.  
  571.     Sub    BX,BX            ;Zero resultant CRC
  572. GetCRCs:Mov    DX,CX
  573.  
  574. GetCRC0:Mov    CX,8            ; bits in a byte
  575.     Lodsb                ; get next byte
  576. GetCRC1:Rol    AL,1            ;MSB -> carry
  577.     Rcl    BX,1            ;    -> CRC LSB
  578.     Jnc    GetCRC2
  579.     Xor    BX,1021h
  580. GetCRC2:Loop    GetCRC1
  581.     Dec    DX
  582.     Jnz    GetCRC0
  583.  
  584.     Mov    AX,BX            ;Return CRC in AX
  585.     Pop    DX
  586.     Pop    BX
  587.     Ret
  588. GetCRC    Endp
  589.  
  590. ;    Update CRC at end of block
  591.  
  592. UpdCRC    Proc    Near            ;CRC in AX
  593.     Push    BX
  594.     Push    DX
  595.     Mov    BX,AX            ;Current CRC
  596.     Mov    CX,2            ;Last two bytes
  597.     Mov    SI,Offset Zero        ; of zero
  598.     Jmp    Short GetCRCs
  599. UpdCRC    Endp
  600.     Page
  601. ;
  602. ;    Get Library file date/time
  603.  
  604. GetDate    Proc    Near            ;Determine original date
  605.     Mov    BX,Handle
  606.     Mov    AX,5700h        ;Get LBR file date/time
  607.     Int    21h            ; in DX:CX
  608.     Push    CX
  609.     Mov    DI,Offset LuDate    ;Convert DOS date
  610.     Call    FixDate
  611.     Pop    DX            ;Convert DOS time
  612.     Mov    DI,Offset LuTime
  613.     Call    FixTime
  614.     Ret
  615.  
  616. ;    Format DOS date
  617.  
  618. FixDate:Mov    AX,DX            ;Get month part
  619.     And    AX,Mask Mo
  620.     Mov    CL,Mo
  621.     Call    Cnvrt
  622.     Mov    AL,'/'
  623.     Stosb                ;Add delimiter
  624.  
  625.     Mov    AX,DX            ;Get day part
  626.     And    AX,Mask Dy
  627.     Call    Cnvrt1
  628.     Mov    AL,'/'
  629.     Stosb                ;Add delimiter
  630.  
  631.     Mov    AX,DX            ;Get year part
  632.     And    AX,Mask Yr
  633.     Mov    CL,Yr
  634.     Shr    AX,CL
  635.     Add    AL,80
  636.     Jmp    Cnvrt1
  637.  
  638. ;    Format DOS time
  639.  
  640. FixTime:Mov    AX,DX            ;Get hour part
  641.     And    AX,Mask Hh
  642.     Mov    CL,Hh
  643.     Call    Cnvrt
  644.     Mov    AL,':'
  645.     Stosb                ;Add delimiter
  646.  
  647.     Mov    AX,DX            ;Get min part
  648.     And    AX,Mask Mm
  649.     Mov    CL,Mm
  650.     Call    Cnvrt
  651.     Mov    AL,':'
  652.     Stosb                ;Add delimiter
  653.  
  654.     Mov    AX,DX            ;Get secs part
  655.     And    AX,Mask Xx
  656.     Add    AX,AX
  657.     Jmp    Short Cnvrt1
  658.  
  659. Cnvrt:    Shr    AX,CL            ;Convert to ASCII
  660. Cnvrt1:    Aam
  661.     Or    AX,'00'
  662.     Xchg    AH,AL
  663.     Stosw
  664.     Ret
  665. GetDate    Endp
  666.     Page
  667. ;
  668. ;    Format CPM date
  669.  
  670. CPM_Date Proc    Near            ;Convert CP/M date
  671.     Push    AX            ; DI points to target
  672.     Push    CX            ; DX contains CPM date
  673.     Push    SI
  674.  
  675.     Mov    AX,DX            ;Days since 12/31/77
  676.     Sub    CX,CX            ;Years since
  677.     Mov    DX,OneYear
  678. CD1:    Sub    AX,DX            ; for 1978
  679.     Jle    CD2
  680.     Inc    CL
  681.     Sub    AX,DX            ; for 1979
  682.     Jle    CD2
  683.     Inc    CL
  684.     Inc    DX
  685.     Sub    AX,DX            ; for next leap year
  686.     Jle    CD2
  687.     Dec    DX
  688.     Inc    CL
  689.     Sub    AX,DX            ; and year after
  690.     Jle    CD2
  691.     Inc    CL
  692.     Jmp    Short CD1
  693.  
  694. CD2:    Add    AX,DX
  695.     Mov    DX,AX            ;Save days left over
  696.  
  697. CD3:    Mov    AX,CX            ;Adjust year
  698.     Add    AL,78            ; plus base year
  699.  
  700.     Mov    Days+1,28        ;Days in Feb
  701.     Test    AL,3            ;Is it leap year?
  702.     Jnz    CD4            ; no, has 28
  703.     Mov    Days+1,29        ; yes, has one more
  704.  
  705. CD4:    Push    AX            ;Save year
  706.     Mov    SI,Offset Days        ; point to days/month
  707.     Sub    AX,AX
  708.     Mov    CL,1            ; month number
  709. CD5:    Lodsb
  710.     Sub    DX,AX            ; days into month
  711.     Jle    CD6            ; within month
  712.     Inc    CL
  713.     Jmp    Short CD5
  714.  
  715. CD6:    Add    DX,AX
  716. CD7:    Mov    AX,CX            ;Format month
  717.     Call    Cnvrt1
  718.  
  719.     Mov    AX,DX            ;Format day
  720.     Inc    DI
  721.     Call    Cnvrt1
  722.  
  723.     Pop    AX            ;Format year
  724.     Inc    DI
  725.     Call    Cnvrt1
  726.  
  727.     Pop    SI
  728.     Pop    CX
  729.     Pop    AX
  730.     Ret
  731.  
  732. Days    Db     31,28,31,30,31,30,31,31,30,31,30,31
  733. OneYear    Equ    365            ;Days in normal year
  734. CPM_Date Endp
  735.     Page
  736. ;
  737. ;  Format a double word    value
  738.  
  739. Format    Proc    Near            ;Format    a block    number
  740.     Sub    DX,DX
  741. Formatd:Push    AX            ;Value in DX:AX
  742.     Push    DI            ;Offset    to target
  743.     Push    BX
  744.     Push    CX
  745.     Push    SI
  746.  
  747.     Mov    BX,DI            ;Save target offset
  748.     Mov    CX,6            ;Clear target to blanks
  749.     Mov    SI,Offset Blanks
  750.     Rep    Movsb
  751.  
  752.     Mov    CX,4            ;Divide    sucessively by
  753.     Sub    SI,SI            ; powers of ten
  754.     Mov    DI,BX            ;Restore target    ptr
  755. Form1:    Or    AX,AX            ;It is zero?
  756.     Jnz    Form1d
  757.     Or    DX,DX
  758.     Jz    Form2
  759. Form1d:    Div    TenK[SI]
  760.     Aam                ;Make AL into BCD
  761. Form2:    Or    AX,'00'            ; and to ASCII
  762.     Xchg    AL,AH
  763.     Or    Byte Ptr [DI],AL
  764.     Mov    Byte Ptr [DI]+1,AH
  765.     Inc    DI            ;Next digit
  766.     Inc    SI            ;Next divisor
  767.     Inc    SI
  768.     Mov    AX,DX            ;Copy remainder
  769.     Sub    DX,DX            ; and clear hi-word
  770.     Loop    Form1
  771.  
  772.     Aam                ;Make AL into BCD
  773.     Or    AX,'00'            ; and to ASCII
  774.     Xchg    AL,AH
  775.     Mov    Byte Ptr [DI]+1,AH
  776.     Mov    CL,5            ;Suppress leading zeros
  777.     Mov    DI,BX            ;Get target offset back
  778.     Mov    AL,' '
  779. Form3:    Cmp    Byte Ptr [DI],'0'
  780.     Jne    Form4
  781.     Stosb
  782.     Loop    Form3
  783.  
  784. Form4:    Pop    SI
  785.     Pop    CX
  786.     Pop    BX
  787.     Pop    DI
  788.     Pop    AX
  789.     Ret
  790.  
  791. TenK    Dw    10000,1000,100,10    ;For converting    numbers
  792. Format    Endp
  793.     Page
  794. ;
  795. ;    Print String
  796.  
  797. PrintS    Proc    Near            ;Print string like Int 21h (9)
  798.     Push    BX            ;DX points to string
  799.     Push    BP
  800.     Push    SI
  801.     Mov    SI,DX
  802. PS1:    Lodsb
  803.     Cmp    AL,0            ;Skip zeros
  804.     Je    PS1
  805.     Cmp    AL,Stopper        ;String    ends in    a hex FF
  806.     Je    PS9            ; so can print $
  807.     Mov    AH,2            ;Display output    to standrd dev
  808.     Mov    DL,AL
  809.     Int    21h
  810.     Jmp    Short PS1
  811.  
  812. PS9:    Pop    SI
  813.     Pop    BP
  814.     Pop    BX
  815.     Ret
  816. PrintS    Endp
  817.     Page
  818. ;
  819. ;    Get command operands
  820.  
  821. GetParm    Proc    Near            ;Operand is LBR name
  822.     Mov    DI,Offset FileNm
  823.     Mov    CX,38
  824.     Sub    AX,AX            ;Clear filename
  825.     Rep    Stosw            ; to zeros
  826.     Mov    AL,Stopper
  827.     Stosb                ; and append stopper
  828.  
  829.     Mov    SI,82h            ;Point to command tail
  830.     Mov    DI,Offset FileNm    ; and target
  831.     Or    CL,DS:[80h]        ;Length of parameters
  832.     Jnz    Copy1
  833.     Jmp    Copy8            ; none, list all LBR
  834.  
  835. Copy1:    Lodsb                ;Skip leading blanks
  836.     Cmp    AL,' '            ; while copying LBR name
  837.     Loope    Copy1
  838. Copy2:    Stosb                ;Copy non-blanks
  839.     Lodsb
  840.     Cmp    AL,0Dh            ;End of parameters?
  841.     Je    Copy3            ; yes, done
  842.     Cmp    AL,' '            ; no, have blank at end?
  843.     Loopne    Copy2            ; if not, just copy
  844.  
  845. ; Set new disk from specified drive
  846.  
  847. Copy3:    Mov    Filend,DI        ;Save end of name ptr
  848.     Cmp    FileNm+1,':'        ;If a drive is specified,
  849.     Jne    Copy4
  850.  
  851.     Mov    AH,19h            ;Save current disk
  852.     Int    21h
  853.     Mov    CurDisk,AL
  854.  
  855.     Mov    DL,Byte Ptr FileNm    ;Set new current disk
  856.     And    DL,0DFh
  857.     Sub    DL,'A'
  858.     Mov    AH,0Eh
  859.     Int    21h
  860.     Mov    FilePtr,Offset FileNm+2
  861.  
  862. ; Determine if any path specified in command
  863.  
  864. Copy4:    Mov    SI,FilePtr        ;First possible filename char
  865.     Lodsb
  866.     Cmp    AL,0            ;Just drive?
  867.     Je    Copy8            ; yes, append default fname
  868.     Cmp    AL,'\'            ;Was a path specified?
  869.     Je    CopyP
  870.     Cmp    AL,'/'
  871.     Jne    Copy9            ; no, see if fname has ext
  872.  
  873. CopyP:    Mov    AH,47h            ; yes, save original path
  874.     Sub    DL,DL            ; for target drive
  875.     Mov    SI,Offset Oldpath+1
  876.     Int    21h
  877.  
  878. ; Set new current directory from command's path
  879.  
  880. Copy5:    Mov    AH,3Bh            ;Set new path
  881.     Mov    DX,FilePtr
  882.     Int    21h
  883.     Jnc    Copy7            ; if path only
  884.     Mov    SI,Filend        ;Have filename after path
  885.     Std
  886.     Mov    CX,SI            ;Length so far
  887.     Sub    CX,FilePtr
  888. Copy6:    Lodsb
  889.     Cmp    AL,'\'            ;Last path name?
  890.     Loopne  Copy6
  891.     Inc    SI            ; yes, mark filename spot
  892.     Mov    Byte Ptr [SI],0        ; and reset ASCIIZ path name
  893.     Inc    SI
  894.     Mov    DX,FilePtr
  895.     Mov    FilePtr,SI        ;Ptr to filename part
  896.     Mov    AH,3Bh
  897.     Int    21h
  898.     Jmp    Short Copy9        ; and check ext
  899. Copy7:
  900.     Mov    SI,Filend        ;Filename ptr at
  901.     Mov    FilePtr,SI        ; end of path name
  902.  
  903. ;    Append *.LBR if no fname
  904.  
  905. Copy8:    Cld
  906.     Mov    SI,FilePtr
  907.     Cmp    Byte Ptr [SI],0
  908.     Jne    Copy9
  909.     Mov    DI,Filend        ;Append default spec
  910.     Mov    SI,Offset Default    ; after path-only name
  911.     Mov    CX,6
  912.     Rep    Movsb
  913.     Jmp    Short CopyC        ; all done
  914.  
  915. ;    Append LBR extension if none supplied
  916.  
  917. Copy9:    Cld
  918.     Mov    SI,FilePtr        ;Find any EXT
  919.     Mov    CX,13            ; in filename
  920. CopyA:    Lodsb
  921.     Cmp    AL,' '
  922.     Ja    CopyB            ; no ext
  923.     Dec    SI
  924.     Mov    Word Ptr [SI],'L.'    ; default to .LBR
  925.     Mov    Word Ptr 2[SI],'RB'
  926.     Jmp    Short CopyC
  927.  
  928. CopyB:    Cmp    AL,'.'            ;Found extension?
  929.     Loopne    CopyA            ; not yet
  930.  
  931. CopyC:;    Mov    DX,Offset FileNm
  932. ;    Call    PrintS
  933.     Ret
  934. GetParm    Endp
  935.  
  936.     Subttl    --- SORT Subroutine ---
  937.     Page
  938. ;
  939. ;    Bubble sort of directory names, CX=number of entries
  940.  
  941. ;    Sort variables
  942.  
  943. Count2    Dw    0            ;Loop counter
  944. First    Dw    0            ;Offset to starting entry
  945. Second    Dw    0            ;Offset to next entry to comp
  946. Len    Equ    32            ;Length of each entry
  947. KeyLen    Equ    11            ;Length of key
  948.  
  949. Sort    Proc    Near            ;Nothing fancy here
  950.     Mov    AX,Entries        ;Sort into name order
  951.     Mov    DI,A_Buf        ;Offset to array
  952.  
  953.     Dec    AX            ; less one as loop limit
  954.     Jz    Sorted            ;Only one
  955.     Js    Sorted            ; or none
  956.     Mov    Count2,AX        ;Save loop limit
  957.  
  958. Sortit:    Mov    First,DI        ;Offset to first entry
  959.     Mov    Second,DI
  960.  
  961. Sort1:    Mov    DX,Count2        ;Save limit count
  962.  
  963. Sort2:    Mov    SI,First        ;First entry to
  964.     Inc    SI
  965.     Mov    DI,Second        ; compare to next entry
  966.     Add    DI,Len
  967.     Mov    Second,DI
  968.     Inc    DI
  969.     Mov    CX,KeyLen
  970.     Repe    Cmpsb            ;Compare elements
  971.     Jbe    Sort3            ; if in order, no swap
  972.  
  973. Swap:    Mov    DI,Second        ; else swap
  974.     Mov    SI,First
  975.     Mov    CX,Len
  976. Xchng:
  977.     Mov    AH,Byte Ptr [SI]
  978.     Mov    AL,Byte Ptr [DI]
  979.     Xor    AH,AL
  980.     Xor    AL,AH
  981.     Xor    AH,AL
  982.     Mov    Byte Ptr [SI],AH
  983.     Stosb
  984.     Inc    SI
  985.     Loop    Xchng
  986.  
  987. Sort3:    Dec    DX
  988.     Jnz    Sort2
  989.     Dec    Count2
  990.     Jz    Sorted
  991.     Mov    AX,Len            ;Bump to next entry
  992.     Add    AX,First        ; for next loop
  993.     Mov    First,AX
  994.     Mov    Second,AX
  995.     Jmp    Short Sort1
  996.  
  997. Sorted:    Ret
  998. Sort    Endp
  999.     Page
  1000. Storage    Equ    This Byte
  1001. Stackx    Equ    Storage+256        ; Local stack end
  1002. DTA    Equ    Stackx+4        ; Data transfer area
  1003. FileNm    Equ    DTA+78            ; Requested file name
  1004. Oldpath    Equ    FileNm+78        ; Target disk original path
  1005. LstPath Equ    OldPath+1
  1006. DirBuf    Equ    OldPath+78        ; 8K directory buffer
  1007.  
  1008. Paras    Equ    ($-Cseg+10240)/16    ; Paragraphs in program
  1009.                     ;  including stack and patch area
  1010. Lut    Endp
  1011.  
  1012. Cseg    Ends
  1013.     End    Lut
  1014.