home *** CD-ROM | disk | FTP | other *** search
/ Oakland CPM Archive / oakcpm.iso / sigm / vol279 / tail.asm < prev    next >
Encoding:
Assembly Source File  |  1986-06-11  |  8.0 KB  |  515 lines

  1. ;    THIS PROGRAM PRINTS THE LAST FEW LINES OF A TEXT FILE.
  2. ;
  3. ;    USAGE:    TAIL -n filename
  4. ;        -n is optional, limits output to n lines (20 default)
  5. ;
  6. ;    BY JON DART, DEPT. OF ANTHROPOLOGY, UCSD C-001, LA JOLLA, CA 92093
  7. ;
  8. ;    VERSION 1.1: 15-MAR-85
  9. ;    VERSION 1.0: 15-JAN-85
  10. ;
  11. BUFSIZ    EQU    64        ;SIZE OF BUFFER IN RECORDS
  12.  
  13. ;    CP/M SYSTEM DEFINITIONS:
  14.  
  15. BOOT    EQU    0
  16. BDOS    EQU    0005H
  17. DEFFCB    EQU    005CH
  18. DEFBUF    EQU    0080H
  19. FCBSIZ    EQU    36
  20. SECSIZ    EQU    128
  21. R0    EQU    33
  22. R2    EQU    35
  23.  
  24. CONOUT    EQU    2
  25. PRTSTR    EQU    09H
  26. VERS    EQU    0CH
  27. FOPEN    EQU    0FH
  28. FCLOSE    EQU    10H
  29. SETDMA    EQU    1AH
  30. RDRAND    EQU    21H
  31. CFS    EQU    23H
  32.  
  33. ;    ASCII CHARACTERS:
  34.  
  35. LF    EQU    0AH
  36. CR    EQU    0DH
  37. TAB    EQU    09H
  38. SPACE    EQU    20H
  39. CTRL$Z    EQU    26
  40.  
  41.     ORG    100H
  42.  
  43. TAIL    EQU    $
  44.     LXI    H,0
  45.     DAD    SP
  46.     SHLD    OLDSTK        ;SAVE OLD STACK POINTER
  47.     LXI    SP,STACK
  48.     CALL    CRLF
  49.     MVI    C,VERS
  50.     CALL    BDOS
  51.     MOV    A,L
  52.     CPI    20H
  53.     JNC    VERSOK        ;IF NOT CP/M 2.2
  54.     LXI    D,MSG0
  55.     MVI    C,PRTSTR
  56.     CALL    BDOS
  57.     JMP    EXIT2
  58. VERSOK: LXI    H,FCB
  59.     MVI    B,FCBSIZ
  60.     CALL    ZERO        ;ZERO FCB
  61.     LXI    H,DEFBUF    ;GET BYTE COUNT FOR COMMAND LINE
  62.     MOV    A,M
  63.     ANA    A
  64.     JZ    NONAME        ;IF NO NAME
  65.     PUSH    H
  66.     MOV    E,M
  67.     MVI    D,0
  68.     DAD    D
  69.     INX    H
  70.     MVI    M,0        ;PUT 0 BYTE AT END OF COMMAND LINE
  71.     POP    H
  72.     INX    H
  73.     CALL    SKIPS        ;SKIP SPACES
  74.     JC    NONAME        ;IF END OF LINE
  75.     CPI    '-'
  76.     JNZ    NONUM        ;IF NO NUMBER SPECIFIED
  77.     INX    H
  78.     MVI    C,0
  79.     PUSH    H
  80. CD:    MOV    A,M        ;HAVE NUMBER, COUNT NUMBER OF DIGITS
  81.     CPI    '0'
  82.     JC    NODGT
  83.     CPI    '9'+1
  84.     JNC    NODGT
  85.     INX    H
  86.     INR    C
  87.     JMP    CD
  88. NODGT:    SHLD    NUMEND        ;SAVE ADDRESS AFTER NUMBER
  89.     POP    H
  90.     CALL    DTOBIN        ;CONVERT NUMBER TO BINARY
  91.     JC    NONAME        ;IF ERROR
  92.     XCHG
  93.     INX    H
  94.     SHLD    NUMLIN        ;STORE AS # LINES
  95.     LHLD    NUMEND        ;POINT TO 1 PAST NUMBER
  96.     CALL    SKIPS
  97.     JC    NONAME
  98. NONUM:    LXI    D,FCB
  99.     CALL    PACK        ;MOVE NAME INTO FCB
  100.     JMP    NAMEOK
  101. NONAME: LXI    D,MSG1
  102.     MVI    C,PRTSTR
  103.     CALL    BDOS
  104.     JMP    EXIT2
  105. NAMEOK:
  106.     LXI    D,FCB
  107.     MVI    C,FOPEN
  108.     PUSH    D
  109.     CALL    BDOS        ;TRY TO OPEN FILE
  110.     POP    D
  111.     CPI    0FFH
  112.     JNZ    OPENOK        ;IF OK
  113. BADOPN: XCHG
  114.     LXI    D,FILNAM
  115.     CALL    FCOPY        ;COPY FILE NAME INTO MESSAGE
  116.     LXI    D,MSG2
  117.     MVI    C,PRTSTR
  118.     CALL    BDOS        ;PRINT MESSAGE
  119.     JMP    EXIT
  120.  
  121. SKIPS1: INX    H
  122. SKIPS:    MOV    A,M
  123.     ANA    A
  124.     STC
  125.     RZ
  126.     CPI    SPACE
  127.     JZ    SKIPS1
  128.     CPI    TAB
  129.     JZ    SKIPS1
  130.     ANA    A
  131.     RET
  132.  
  133. ;    COPY FILE NAME FROM COMMAND LINE TO FCB
  134. ;    ENTRY: (HL) POINTS TO FILE NAME
  135. ;           (DE) POINTS TO FCB
  136. ;
  137. PACK:    INX    H
  138.     MOV    A,M
  139.     CPI    ':'
  140.     DCX    H
  141.     JZ    HAVED        ;IF DRIVE SPECIFIED
  142.     XRA    A
  143.     STAX    D        ;ELSE PUT 0 IN 1ST BYTE
  144.     JMP    PACK2
  145. HAVED:    MOV    A,M
  146.     SUI    'A'-1
  147.     STAX    D
  148.     INX    H
  149.     INX    H
  150. PACK2:    INX    D
  151.     PUSH    H
  152.     PUSH    D
  153.     XCHG
  154.     MVI    B,11
  155.     MVI    A,SPACE
  156.     CALL    FILL        ;FILL NAME FIELD WITH SPACES
  157.     POP    D
  158.     POP    H
  159.     MVI    C,8
  160. PACK3:    MOV    A,M        ;COPY NAME
  161.     ANA    A
  162.     RZ
  163.     CPI    SPACE
  164.     RZ
  165.     INX    H
  166.     CPI    '.'
  167.     JZ    PACK4
  168.     STAX    D
  169.     INX    D
  170.     DCR    C
  171.     JNZ    PACK3
  172.     MOV    A,M                        ;15-MAR-85
  173.     ANA    A                        ;15-MAR-85
  174.     RZ                            ;15-MAR-85
  175.     INX    H        ;FIXES BUG            ;15-MAR-85
  176.     JMP    PACK5
  177. PACK4:    XCHG
  178.     MOV    B,C
  179.     MVI    A,SPACE
  180.     CALL    FILL
  181.     XCHG
  182. PACK5:    MVI    C,3        ;COPY EXTENSION
  183. PACK6:    MOV    A,M
  184.     ANA    A
  185.     RZ
  186.     CPI    SPACE
  187.     RZ
  188.     STAX    D
  189.     INX    H
  190.     INX    D
  191.     DCR    C
  192.     JNZ    PACK6
  193.     RET
  194.  
  195. ZERO:    XRA    A
  196. FILL:    MOV    M,A
  197.     INX    H
  198.     DCR    B
  199.     JNZ    FILL
  200.     RET 
  201.  
  202. OPENOK    EQU    $
  203.     LXI    D,FCB
  204.     MVI    C,CFS
  205.     CALL    BDOS        ;COMPUTE FILE SIZE
  206.     LHLD    FCB+R0        ;GET SIZE
  207.     MOV    A,L
  208.     ORA    H
  209.     JZ    EXIT        ;IF 0
  210.     SHLD    FILSIZ        ;SAVE SIZE
  211.     LXI    D,BUFSIZ
  212.     CALL    SUBHLDE        ;SUBTRACT BUFFER SIZE
  213.     JC    SMALL        ;IF FILE SIZE < BUFFER SIZE
  214.     PUSH    H
  215.     LXI    H,BUFSIZ    ;SET BUFFER SIZE
  216.     SHLD    NREAD        ;AS NUMBER OF RECORDS TO READ
  217.     POP    H
  218.     JMP    GOTSIZ
  219. SMALL:    LHLD    FILSIZ        ;SET FILE SIZE
  220.     SHLD    NREAD        ;AS NUMBER OF RECORDS TO READ
  221.     LXI    H,0        ;START FROM RECORD 0
  222. GOTSIZ: SHLD    FCB+R0        ;SET RANDOM RECORD BYTES
  223.     CALL    FILBUF        ;FILL BUFFER FROM DISK
  224.     LHLD    NREAD
  225.     DCX    H
  226.     PUSH    H
  227.     POP    B
  228.     LXI    D,SECSIZ
  229.     LXI    H,BUFFER
  230. MLOOP:    MOV    A,B        ;COMPUTE ADDRESS OF START OF LAST SECTOR
  231.     ORA    C
  232.     JZ    MDONE
  233.     DAD    D
  234.     DCX    B
  235.     JMP    MLOOP
  236. MDONE:    MVI    C,SECSIZ
  237. FCZ:    MOV    A,M        ;SEARCH FOR ^Z
  238.     CPI    CTRL$Z
  239.     JZ    FOUND
  240.     INX    H
  241.     DCR    C
  242.     JNZ    FCZ
  243. FOUND:    SHLD    ENDTXT        ;SAVE END OF TEXT ADDRESS
  244.     LXI    D,BUFFER
  245.     DCX    H        ;POINT TO CHAR. BEFORE ^Z
  246.     PUSH    H
  247.     LHLD    NUMLIN
  248.     PUSH    H
  249.     POP    B        ;LINE COUNT IN (BC)
  250.     POP    H
  251. SRC:    CALL    COMPRP
  252.     JZ    BEGIN        ;IF REACHED START OF BUFFER
  253.     MOV    A,M        ;GET BYTE
  254.     DCX    H
  255.     CPI    LF
  256.     JZ    GOTLF        ;IF LF
  257.     CPI    CR
  258.     JNZ    SRC        ;IF NOT CR
  259. GOTCR:    DCX    B        ;FOUND CR, COUNT A LINE
  260.     MOV    A,M        ;GET PREVIOUS CHAR.
  261.     CPI    LF        ;IF LF,
  262.     JNZ    NOSKIP
  263.     DCX    H        ;SKIP IT
  264. NOSKIP: MOV    A,B        ;GET LINE COUNT
  265.     ORA    C        ;MORE TO GO?
  266.     JNZ    SRC        ;YES, LOOP
  267.     INX    H        ;START OF RIGHT LINE FOUND
  268.     JMP    BEGIN        ;GO PRINT
  269. GOTLF:    DCX    B        ;COME HERE IF FOUND LF
  270.     MOV    A,M        ;IF PREVIOUS CHAR. = CR
  271.     CPI    CR
  272.     JNZ    NOSKIP
  273.     DCX    H        ;SKIP IT
  274.     JMP    NOSKIP
  275. BEGIN:    PUSH    H
  276.     LHLD    ENDTXT
  277.     XCHG            ;PUT END OF BUFFER ADDR. IN (DE)
  278.     POP    H
  279. SHOW:    CALL    COMPRP        ;DISPLAY TEXT
  280.     JZ    EXIT        ;UNTIL END OF BUFFER
  281.     MOV    A,M
  282.     CALL    COUT
  283.     INX    H
  284.     JMP    SHOW
  285.  
  286. ;    FILBUF - FILL BUFFER FROM FILE
  287. ;
  288. ;    ENTRY:    NONE
  289. ;
  290. ;    EXIT:    'C'=1 IF ERROR
  291. ;
  292. FILBUF    EQU    $
  293.     LXI    D,BUFFER    ;BUFFER ADDRESS IN (DE)
  294.     LHLD    NREAD
  295.     PUSH    H
  296.     POP    B        ;(BC) = COUNT OF SECTORS TO READ
  297. READ11: PUSH    D
  298.     PUSH    B
  299.     MVI    C,SETDMA
  300.     CALL    BDOS        ;SET DMA ADDRESS
  301.     LXI    D,FCB
  302.     MVI    C,RDRAND
  303.     CALL    BDOS        ;READ A SECTOR
  304.     ANA    A
  305.     POP    B
  306.     POP    D
  307.     JNZ    READ12        ;QUIT IF END OF FILE
  308.  
  309.     DCX    B        ;COUNT # SECTORS READ
  310.     XCHG
  311.     LXI    D,SECSIZ
  312.     DAD    D        ;UPDATE BUFFER ADDRESS
  313.     XCHG
  314.     LHLD    FCB+R0
  315.     INX    H        ;ADVANCE FCB
  316.     SHLD    FCB+R0        ;TO NEXT SECTOR
  317.     MOV    A,C        ;GET # SECTORS TO READ
  318.     ORA    B
  319.     JNZ    READ11        ;LOOP TILL DONE
  320.  
  321. READ12: ANA    A        ;CLEAR CARRY
  322.     RET
  323.  
  324. EXIT:    LXI    D,FCB        ;CLOSE FILE
  325.     MVI    C,FCLOSE
  326.     CALL    BDOS
  327. EXIT2:    LHLD    OLDSTK
  328.     SPHL
  329.     RET            ;RETURN TO CCP
  330.  
  331. FCOPY:    MOV    A,M
  332.     INX    H
  333.     ANA    A
  334.     JZ    NODRV
  335.     ADI    'A'-1
  336.     STAX    D
  337.     INX    D
  338.     MVI    A,':'
  339.     STAX    D
  340.     INX    D
  341. NODRV:    MVI    B,11
  342. FCOPY1: MOV    A,M
  343.     CPI    SPACE
  344.     JZ    NOCOPY
  345.     STAX    D
  346.     INX    D
  347. NOCOPY: INX    H
  348.     DCR    B
  349.     RZ
  350.     MOV    A,B
  351.     CPI    3
  352.     JNZ    FCOPY1
  353.     MVI    A,'.'
  354.     STAX    D
  355.     INX    D
  356.     JMP    FCOPY1
  357.  
  358. ;    UTILITY SUBROUTINES:
  359.  
  360. ;    DTOBIN - CONVERT A 5-DIGIT (MAX.) UNSIGNED DECIMAL NUMBER INTO A
  361. ;    BINARY VALUE.
  362. ;
  363. ;    ENTRY:    (C) = NO. OF DIGITS
  364. ;        (HL)  POINTS TO CHAR. STRING (MSD FIRST)
  365. ;
  366. ;    EXIT:    (DE) = CONVERTED NUMBER
  367. ;        'C' FLAG SET IF OVERFLOW (>64384) OR ERROR
  368. ;
  369. ;    USES:    ALL 8080 REGS.
  370. ;
  371. DGTPTR: DS    2
  372. DTOBIN: XRA    A
  373.     MOV    D,A
  374.     MOV    E,A        ;CLEAR (DE) - SERVES AS ACCUMULATOR
  375.     CMP    C        ;MAKE SURE (C) NOT ZERO
  376.     RZ
  377.     PUSH    H
  378. DTOB:    SHLD    DGTPTR        ;SAVE (HL) AS DIGIT POINTER
  379.     MOV    A,M        ;GET DIGIT
  380.     POP    H
  381.     CALL    VALDGT        ;CHECK FOR VALID DECIMAL DIGIT
  382.     RC            ;RETURN WITH ERROR IF NOT
  383.     ANI    0FH        ;CONVERT ASCII DIGIT TO BINARY
  384.     XCHG            ;SAVE SUM IN (HL)
  385.     MOV    E,A        ;MOVE DIGIT TO (DE)
  386.     MVI    D,0
  387.     MOV    B,C
  388.     DCR    B        ;PUT COUNT IN (B) = DIGIT COUNT -1
  389.     JZ    DTOB$1        ;IF =0, SKIP X10 ROUTINE
  390. DEX10:    PUSH    H
  391.     CALL    MU10        ;MULTIPLY (DE) BY 10
  392.     XCHG
  393.     POP    H
  394.     RC            ;(B) TIMES - RETURN ON OVERFLOW
  395.     DCR    B
  396.     JNZ    DEX10
  397. DTOB$1: DAD    D        ;ADD PRODUCT TO RESULT
  398.     RC            ;RETURN ON OVERFLOW
  399.     XCHG            ;SAVE NEW SUM
  400.     DCR    C
  401.     RZ            ;FINISHED IF COUNT=0
  402.     PUSH    H
  403.     LHLD    DGTPTR
  404.     INX    H        ;ELSE BUMP DIGIT POINTER
  405.     JMP    DTOB        ;& CONVERT NEXT DIGIT
  406. MU10:    XCHG
  407.     DAD    H
  408.     RC
  409.     MOV    D,H
  410.     MOV    E,L
  411.     DAD    H
  412.     RC
  413.     DAD    H
  414.     RC
  415.     DAD    D
  416.     RET
  417.  
  418. ;    SUBROUTINE - RETURNS WITH 'C' FLAG SET IF CHAR. IN (A) IS NOT
  419. ;    IN THE RANGE 0-9
  420.  
  421. VALDGT: CPI    '0'
  422.     RC
  423.     CPI    ':'
  424.     CMC
  425.     RET
  426.  
  427. ;    CHARACTER OUTPUT
  428.  
  429. COUT:    DS    0
  430.     PUSH    H
  431.     PUSH    D
  432.     PUSH    B
  433.     PUSH    PSW
  434.     ANI    07FH
  435.     MOV    E,A
  436.     MVI    C,CONOUT
  437.     CNZ    BDOS
  438.     POP    PSW
  439.     POP    B
  440.     POP    D
  441.     POP    H
  442.     RET
  443.  
  444. ;    WRITE CR + LF
  445.  
  446. CRLF:    MVI    A,CR
  447.     CALL    COUT
  448.     MVI    A,LF
  449.     JMP    COUT
  450.  
  451. ;    COMPRP = COMPARE REGISTER PAIR
  452. ;
  453. ;    ENTRY:    (HL), (DE) SET
  454. ;
  455. ;    EXIT:    'Z'=1 IF (HL)=(DE)
  456. ;        'C'=1 IF (HL)>(DE)
  457. ;
  458. COMPRP: MOV    A,D
  459.     CMP    H
  460.     RNZ
  461.     MOV    A,E
  462.     CMP    L
  463.     RET
  464.  
  465. ;    SUBHLDE = SUBTRACT (DE) FROM (HL)
  466. ;
  467. ;    ENTRY:    (HL), (DE) SET
  468. ;
  469. ;    EXIT:    (HL) = (HL) - (DE)
  470. ;        'C' AND 'Z' FLAGS REFLECT RESULTS OF SUBTRACTION
  471. ;
  472. ;    USES:    F,H,L  ONLY
  473. ;
  474. SUBHLDE: DS     0
  475.     PUSH    B
  476.     MOV    B,A        ;SAVE (A)
  477.     XCHG
  478.     CALL    COMPRP        ;SET FLAGS
  479.     XCHG
  480.     MOV    A,B        ;RESTORE (A)
  481.     POP    B
  482.     PUSH    PSW        ;SAVE (A) AND FLAGS
  483.     MOV    A,L
  484.     SUB    E
  485.     MOV    L,A        ;DO SUBTRACTION
  486.     MOV    A,H
  487.     SBB    D
  488.     MOV    H,A
  489.     POP    PSW        ;RESTORE (A) AND FLAGS
  490.     RET
  491.  
  492. ;    MEMORY DEFINITIONS:
  493. ;
  494. FCB:    DS    FCBSIZ
  495. OLDSTK: DS    2        ;STACK POINTER ON ENTRY
  496. ENDTXT: DS    2        ;END OF TEXT IN BUFFER
  497. FILSIZ: DS    2        ;FILE SIZE IN RECORDS
  498. NREAD:    DS    2        ;NUMBER OF RECORDS TO READ FROM FILE
  499. NUMEND: DS    2        ;END OF NUMBER
  500.     DS    40        ;STACK AREA
  501. STACK:    DS    0        ;TOP OF STACK
  502. NUMLIN: DW    20        ;NUMBER OF LINES TO LIST
  503. MSG0:    DB    CR,LF,'CP/M 2.X REQUIRED.',CR,LF,'$'
  504. MSG1:    DB    'TAIL V. 1.1 BY JON DART'
  505.     DB    CR,LF,CR,LF
  506.     DB    'USAGE: TAIL -n filename',CR,LF
  507.     DB    SPACE,SPACE,SPACE,SPACE,SPACE,SPACE,SPACE
  508.     DB    '-n is optional, shows last n lines of file (default 20)','$'
  509. MSG2:    DB    CR,LF,'CAN''T OPEN: '
  510. FILNAM: DB    0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,CR,LF,'$'
  511.  
  512. ENDDATA EQU    $
  513. BUFFER    EQU    ENDDATA+10;
  514.     END
  515.