home *** CD-ROM | disk | FTP | other *** search
/ Oakland CPM Archive / oakcpm.iso / cpm / cpm86 / lu86-2.lbr / LDIR86.AQ6 / ldir6.a86
Text File  |  1987-11-22  |  10KB  |  478 lines

  1. ;******************************************************************************
  2. ;
  3. ;    PROGRAM:    LDIR86.A86
  4. ;    VERSION:    1.05
  5. ;    DATE:        10 September 1984
  6. ;    AUTHOR:        Charlie Godet-Ceraolo
  7. ;
  8. ;    DESCRIPTION:    This is a version of LDIR for CP/M86 systems.
  9. ;            It displays a directory of a LBR file.  It accepts
  10. ;            the LBR name on the command line, with or without
  11. ;            the LBR extension.  The Library filename can be
  12. ;            followed by a (possibly ambiguous) filespec
  13. ;            to search for in the library.
  14. ;            Entering nothing on the command line will display
  15. ;            a brief summary of the above.
  16. ;
  17. ;    NOTES:
  18. ;        I wrote the program with a view towards simplicity and clarity
  19. ;        rather than speed or compactness.  If you want to modify it,
  20. ;        here are some things to keep in mind:
  21. ;
  22. ;            1. It uses the 8080 Model
  23. ;            2. It depends heavily on ALL the Segment Registers
  24. ;               pointing to the same area of memory.
  25. ;            3. the ES register is saved across BDOS calls.
  26. ;            4. most routines save all scratch registers except
  27. ;               those returning values.
  28. ;
  29. ;*******************************************************************************
  30. ;
  31. ;    cpm86 equates
  32. ;
  33. WCCFC        EQU    02    ; write console character
  34. OPNFC        EQU    15    ; open file
  35. RSRFC        EQU    20    ; read sequential record from disk
  36. ;
  37. ;    LU Dir entry equates and offsets
  38. ;
  39. ENTRYLEN    EQU    32
  40. ACTIVE        EQU    00H
  41. UNUSED        EQU    0FFH
  42. DELETED        EQU    0FEH
  43. STATUS        EQU     0
  44. NAME        EQU     1
  45. EXTENSION    EQU     9
  46. INDEX        EQU    12
  47. COUNT        EQU    14
  48. CRC        EQU    16
  49. ;
  50. ;    Ascii equates
  51. ;
  52. TAB        EQU    09H
  53. CR        EQU    0DH
  54. LF        EQU    0AH
  55. SPACE        EQU    ' '
  56. ASCII_ZERO    EQU    '0'
  57. EOS        EQU    0H
  58. NUM_ACROSS    EQU    3    ; three across on a line
  59. ;
  60. ; CP/M86's BasePage
  61. ;
  62.         RB    5CH
  63. FCB        EQU    $    ; default fcb
  64. FCBDN        RB    1
  65. FCBFN        RB    8
  66. FCBFT        RB    3
  67. FCBEX        RB    1
  68. FCBS1        RB    1
  69. FCBS2        RB    1
  70. FCBRC        RB    1
  71. FCB2        EQU    $    ; second fcb
  72. FCBD0        RB    16
  73. FCBCR        RB    1
  74. FCBRNO        RB    3
  75. BUFF        EQU    $
  76.         RB    80H    ; default buffer
  77. ;
  78. ;    Set up local stack
  79. ;
  80. LDIR:
  81.         MOV    DX,DS
  82.         MOV    SS,DX
  83.         MOV    SP,OFFSET LOCAL_STACK
  84.         CLD            ; direction flg for increment
  85. ;
  86. ;    Print signon message
  87. ;
  88.         MOV    SI,OFFSET SIGNON
  89.         CALL    PSTRING
  90.         CALL    CRLF
  91. ;
  92. ;    check for command line, display usage if none
  93. ;
  94.         MOV    BX,OFFSET BUFF
  95.         MOV    AL,[BX]
  96.         OR    AL,AL        ; zero means no command
  97.         JNZ    cmdok        ; we got one, proceed
  98. ;
  99. ;    no command line, show usage and exit
  100. ;
  101.         CALL    CRLF
  102.         MOV    SI,OFFSET USEMSG
  103.         CALL    PSTRING
  104.         CALL    CRLF
  105.         JMP    FINIS
  106. ;
  107. ;    check for extension, add LBR if none
  108. ;
  109. cmdok:
  110.         MOV    AL,FCBFT
  111.         CMP    AL,SPACE
  112.         JNZ    extok
  113.         MOV    SI,OFFSET LIBEXT
  114.         MOV    CX,3
  115.         MOV    DI,OFFSET FCBFT
  116.         REP    MOVSB
  117. ;
  118. ;    check for search request, use Joker (*.*) if none
  119. ;
  120. extok:
  121.         MOV    CX,11            ; bytes to move
  122.         MOV    DI,OFFSET SEARCH_STR    ; destination
  123.         MOV    SI,OFFSET FCB2+1    ; assume fcb2
  124.         MOV    AL,[SI]
  125.         CMP    AL,SPACE        ; anything there?
  126.         JNZ    gotaname        ; yes, move it
  127.         MOV    SI,OFFSET JOKER        ; no, move the joker
  128. gotaname:
  129.         REP    MOVSB            ; move it
  130. ;
  131. ;    try to open the file
  132. ;
  133.         CALL    OPEN_FILE
  134.         CMP    AL,255
  135.         JNZ    OPENOK
  136. ;
  137. ;    No file, send message and leave
  138. ;
  139.         MOV    SI,OFFSET OPNMSG
  140.         CALL    PSTRING
  141.         JMP    FINIS
  142. ;
  143. ;    file found and opened, get dir info
  144. ;
  145. OPENOK:
  146.         XOR    AX,AX        ; initialize variables
  147.         MOV    MAX_ENTRIES,AX
  148.         MOV    IN_USE,AX
  149.         MOV    AL,NUM_ACROSS
  150.         MOV    ENTRIES_PRINTED,AL
  151.         CALL    CRLF
  152. ;
  153.         CALL    READ_SECTOR    ; Get first sector
  154.         OR    AL,AL
  155.         JZ    readok        ; if non-zero, we're at eof
  156. ;
  157. ;    premature end of file, send message, and exit
  158. ;
  159.         MOV    SI,OFFSET EOFMSG
  160.         CALL    PSTRING
  161.         JMP    FINIS
  162. readok:
  163.         MOV    BX,OFFSET BUFF    ; point to first entry
  164.         MOV    AX,COUNT[BX]    ; get dir size in sectors
  165.         MOV    CL,2
  166.         SHL    AX,CL        ; sectors * 4 = MAX_ENTRIES
  167.         MOV    MAX_ENTRIES,AX    ; save it
  168.         MOV    ENTRIES_TO_DO,AX    ; and our counter
  169.         INC    IN_USE        ; for the dir header
  170.         DEC    ENTRIES_TO_DO    ; likewise
  171. ;
  172.         ADD    BX,ENTRYLEN    ; point to next entry
  173.         MOV    CX,3        ; allow for dir header
  174. ;
  175. ;    Read and analyze entries until eof
  176. ;
  177. MAIN:
  178.         MOV    AL,STATUS[BX]
  179.         CMP    AL,UNUSED    ; first unused entry?
  180.         JZ    FINALE        ; yes, we're done
  181. ;
  182.         CMP    AL,ACTIVE    ; active entry?
  183.         JNZ    skipit        ; no, don't process it
  184. ;
  185.         INC    IN_USE        ; yes, bump counter
  186.         LEA    DI,NAME[BX]    ; point to name
  187.         CALL    COMPARE        ; does it match?
  188.         OR    AL,AL
  189.         JNZ    skipit        ; nope, skip it
  190.         CALL    DOENTRY        ; else display info
  191. skipit:
  192.         DEC    ENTRIES_TO_DO    ; have we read em all?
  193.         JZ    FINALE        ; yes, leave
  194.         ADD    BX,ENTRYLEN    ; no, point to next entry
  195.         LOOP    MAIN        ; and continue processing
  196. ;
  197.         CALL    READ_SECTOR    ; Get another sector
  198.         OR    AL,AL        ; Eof?
  199.         JNZ    FINALE        ; Yes, leave
  200.         MOV    BX,OFFSET BUFF    ; no, reset buffer pointer
  201.         MOV    CX,4        ; and entries per buffer
  202.         JMP    MAIN        ; and process this sector
  203. ;
  204. ;    display summary information
  205. ;
  206. FINALE:
  207.         CALL    CRLF
  208.         CALL    CRLF
  209.         MOV    SI,OFFSET MAXMSG
  210.         CALL    PSTRING
  211.         MOV    BX,MAX_ENTRIES
  212.         CALL    DECIMAL_OUT
  213.         MOV    SI,OFFSET FREEMSG
  214.         CALL    PSTRING
  215.         SUB    BX,IN_USE    ; free slots = max - in use
  216.         CALL    DECIMAL_OUT
  217.         CALL    CRLF
  218. ;
  219. ;    back to CP/M86, the easy way
  220. ;
  221. FINIS:
  222.         MOV    CL,0
  223.         MOV    DX,0
  224.         INT    224
  225. ;
  226. ;            SUBROUTINES
  227. ;
  228. ;    compare filenames, including wildcards
  229. ;    on entry DI points to the filename to match with Search_str
  230. ;    all registers saved. Returns AL = 0 if a match, else AL = FF
  231. ;
  232. COMPARE:
  233.         PUSH    CX
  234.         PUSH    SI
  235.         PUSH    DI
  236.         MOV    SI,OFFSET SEARCH_STR    ; source
  237.         MOV    CX,11            ; number of bytes to compare
  238. cmploop:
  239.         LODS    SEARCH_STR
  240.         CMP    AL,'?'
  241.         JZ    itmatches
  242.         CMP    AL,[DI]
  243.         JNZ    nomatch
  244. itmatches:
  245.         INC    DI
  246.         LOOP    cmploop
  247.         MOV    AL,0            ; if we got this far
  248.         JMP    cmpexit            ; it's a match, send 0
  249. nomatch:
  250.         MOV    AL,0FFH            ; send FF, no match
  251. cmpexit:
  252.         POP    DI
  253.         POP    SI
  254.         POP    CX
  255.         RET
  256. ;
  257. ;    process the entry pointed to by BX, all registers saved
  258. ;
  259. DOENTRY:
  260.         PUSH    BP        ; save scratch registers
  261.         PUSH    SI
  262.         PUSH    AX
  263.         PUSH    CX
  264.         MOV    BP,BX        ; for easier processing
  265.         LEA    SI,NAME[BP]    ; point to the name
  266.         CALL    PFNAME        ; print it
  267.         MOV    BX,COUNT[BP]    ; get the value
  268.         OR    BX,BX        ; is it zero?
  269.         JZ    print_size    ; yes, print it
  270.         MOV    CL,3
  271.         SHR    BX,CL        ; convert to k
  272.         JNZ    print_size    ; print it, if non-zero
  273.         INC    BX        ; otherwise, make it at least one
  274. print_size:
  275.         CALL    DECIMAL_OUT    ; print it
  276.         MOV    AL,'k'
  277.         CALL    WCC
  278.         DEC    ENTRIES_PRINTED
  279.         JNZ    do_separator
  280.         CALL    CRLF
  281.         MOV    AL,NUM_ACROSS
  282.         MOV    ENTRIES_PRINTED,AL
  283.         JMP    no_sep
  284. do_separator:
  285.         MOV    SI,OFFSET SEPARATOR
  286.         CALL    PSTRING
  287. no_sep:
  288.         MOV    BX,BP        ; restore caller's pointer
  289.         POP    CX
  290.         POP    AX
  291.         POP    SI        ; and scratch registers
  292.         POP    BP
  293.         RET
  294. ;
  295. ;    do bdos call, saving ES
  296. ;
  297. BDOS:
  298.         PUSH    ES
  299.         INT    224
  300.         POP    ES
  301.         RET
  302. ;
  303. WCC:
  304.         PUSH    BX
  305.         PUSH    DX
  306.         PUSH    CX
  307.         MOV    CL,WCCFC
  308.         MOV    DL,AL
  309.         CALL    BDOS
  310.         POP    CX
  311.         POP    DX
  312.         POP    BX
  313.         RET
  314. ;
  315. PSPACE:
  316.         PUSH    AX
  317.         MOV    AL,SPACE
  318.         CALL    WCC
  319.         POP    AX
  320.         RET
  321. ;
  322. CRLF:
  323.         PUSH    AX
  324.         MOV    AL,CR
  325.         CALL    WCC
  326.         MOV    AL,LF
  327.         CALL    WCC
  328.         POP    AX
  329.         RET
  330. ;
  331. OPEN_FILE:
  332.         XOR    AL,AL
  333.         MOV    FCBCR,AL
  334.         MOV    FCBEX,AL
  335.         MOV    FCBRC,AL
  336.         MOV    DX,OFFSET FCB
  337.         MOV    CL,OPNFC
  338.         CALL    BDOS
  339.         RET
  340. ;
  341. READ_SECTOR:
  342.         PUSH    BX
  343.         PUSH    DX
  344.         PUSH    CX
  345.         MOV    DX,OFFSET FCB
  346.         MOV    CL,RSRFC
  347.         CALL    BDOS
  348.         POP    CX
  349.         POP    DX
  350.         POP    BX
  351.         RET
  352. ;
  353. ;    Print null-terminated string pointed to by SI, saves all
  354. ;
  355. PSTRING:
  356.         PUSH    AX
  357.         PUSH    SI
  358. pstrloop:
  359.         LODS    BYTE PTR [SI]    ; get a character
  360.         OR    AL,AL        ; machine zero?
  361.         JZ    pstrexit    ; yes, exit
  362.         CALL    WCC        ; print it
  363.         JMP    pstrloop    ; get another
  364. pstrexit:
  365.         POP    SI
  366.         POP    AX
  367.         RET
  368. ;
  369. ;    Print filename pointed to by SI, all regs saved
  370. ;
  371. PFNAME:
  372.         PUSH    AX
  373.         PUSH    CX
  374.         PUSH    SI
  375.         MOV    CX,8        ; number of chars in name
  376. fnameloop:
  377.         LODS    BYTE PTR [SI]
  378.         CALL    WCC
  379.         LOOP    fnameloop
  380.         MOV    AL,'.'
  381.         CALL    WCC
  382.         MOV    CX,3        ; number of chars in extension
  383. extloop:
  384.         LODS    BYTE PTR [SI]
  385.         CALL    WCC
  386.         LOOP    extloop
  387.         POP    SI
  388.         POP    CX
  389.         POP    AX
  390.         RET
  391. ;
  392. ; Print binary number in BX as Ascii decimal digits,
  393. ; replacing leading zeros by blanks.  All regs saved
  394. ;
  395. DECIMAL_OUT:
  396.         PUSH    AX
  397.         PUSH    BX        ; save number
  398.         PUSH    CX        ; and scratch regs
  399.         PUSH    DX
  400.         PUSH    SI
  401. ;
  402.         MOV    SI,0        ;  0 = no digit printed yet
  403.                     ; FF = digit already printed
  404.         MOV    CX,10000
  405.         CALL    PRINT_DIGIT    ; 10 thousands
  406.         MOV    CX,1000
  407.         CALL    PRINT_DIGIT    ; thousands
  408.         MOV    CX,100
  409.         CALL    PRINT_DIGIT    ; hundreds
  410.         MOV    CX,10
  411.         CALL    PRINT_DIGIT    ; tens
  412.         MOV    AL,BL        ; units
  413.         ADD    AL,ASCII_ZERO    ; Ascii bias
  414.         CALL    WCC
  415. ;
  416.         POP    SI
  417.         POP    DX        ; restore registers
  418.         POP    CX
  419.         POP    BX
  420.         POP    AX
  421.         RET            ; and back.
  422. ;
  423. ;    divide number in bx by power of ten in cx.  Return remainder
  424. ;    in bx, and print quotient in al as an ascii digit.
  425. ;
  426. PRINT_DIGIT:
  427.         XOR    DX,DX        ; clear high 16-bits
  428.         MOV    AX,BX        ; number into low 16-bits
  429.         DIV    CX        ; divide by word in cx
  430.         MOV    BX,DX        ; return remainder in bx
  431.         ADD    AL,ASCII_ZERO    ; Ascii bias
  432. ;
  433. ;    Check for zero
  434. ;
  435.         CMP    AL,ASCII_ZERO    ; zero or less?
  436.         JA    nonzero        ; no
  437.         OR     SI,SI        ; yes, check digit printed flag
  438.         JZ    spacexit    ; leading zero --> leading blank
  439.         CALL    WCC        ; print interior zero
  440.         RET
  441. spacexit:
  442.         CALL    PSPACE        ; print leading blank
  443.         RET
  444. ;
  445. nonzero:
  446.         MOV    SI,0FFH        ; set flag for digit printed
  447.         CALL    WCC        ; print it
  448.         RET
  449. ;
  450. ;    initialized data area
  451. ;
  452. SIGNON        DB    'LDIR86 v1.06',EOS
  453. JOKER        DB    '???????????'            ; = '*.*'
  454. USEMSG        DB    TAB,'USAGE: LDIR86 LibName[.LBR] [afn]',CR,LF
  455.         DB    TAB,TAB,'afn = ambiguous file name',EOS
  456. OPNMSG        DB    'Library file not found',EOS
  457. LIBEXT        DB    'LBR',EOS
  458. EOFMSG        DB    'Premature End of File',EOS
  459. SEPARATOR    DB    ' | ',EOS
  460. MAXMSG        DB    'Max Slots:',EOS
  461. FREEMSG        DB    ', Free Slots:',EOS
  462. ;
  463. ;    uninitialized data area
  464. ;
  465. MAX_ENTRIES    RW    1        ; size of dir
  466. IN_USE        RW    1        ; Max - inuse = free
  467. ENTRIES_TO_DO    RW    1        ; how many so far
  468. ENTRIES_PRINTED    RB    1        ; on a line
  469. SEARCH_STR    RS    11        ; for fcb2 fname
  470. ;
  471. ;    stack area
  472. ;
  473.         RB    100
  474. LOCAL_STACK    EQU    $
  475.         DB    0        ; so GENCMD will save data area
  476. ;
  477.         END
  478.