home *** CD-ROM | disk | FTP | other *** search
/ ftp.barnyard.co.uk / 2015.02.ftp.barnyard.co.uk.tar / ftp.barnyard.co.uk / cpm / walnut-creek-CDROM / JSAGE / ZSUS / SUBSCRIP / ZSUS3-03.LZH / CCOUNT10.LBR / CCOUNT10.ZZ0 / CCOUNT10.Z80
Text File  |  1992-03-07  |  21KB  |  751 lines

  1. ; CCOUNT.Z80
  2. ;
  3. ;    Counts characters in text files.
  4. ;
  5. Vers    equ    10
  6. SubVers    equ    ' '
  7. ;
  8. ; HISTORY:
  9. ;
  10. ; Version 1.0 -- March 7, 1992 -- Gene Pizzetta
  11. ;    Based on a very mimimal test program I have used for a long time
  12. ;    (It had the search characters hard coded into it).  I decided that
  13. ;    maybe I should release it after sprucing it up and making some
  14. ;    additions:  entering search bytes on the command line, option
  15. ;    to count all characters, screen paging, 32-bit long-word counters
  16. ;    and display so more than 65,535 characters can be counted, help
  17. ;    screen, etc. etc.  The result is an all-new program.
  18. ;
  19. ; System addresses . . .
  20. ;
  21. CpmFcb    equ    5Ch        ; default file control block
  22. CpmDma    equ    80h        ; default DMA buffer
  23. ;
  24. ; ASCII . . .
  25. ;
  26. CtrlC    equ    03h        ; ^C
  27. TAB    equ    09h        ; tab
  28. LF    equ    0Ah        ; line feed
  29. CR    equ    0Dh        ; carriage return
  30. CtrlS    equ    13h        ; ^S
  31. CpmEof    equ    1Ah        ; ^Z (end-of-file)
  32. ;
  33. ; Program specifications . . .
  34. ;
  35. NumSiz    equ    10        ; minimum length of long-word output
  36. BufSiz    equ    8        ; buffer size in records (sectors)
  37. ;
  38.     .request    zslib,z3lib,syslib
  39. ;
  40.     ext    eatspc,eatnspc,zcheck,fxropen,fxrclose,fxget    ; ZSLIB
  41.     ext    parcnt,parget,uncaps,hvtinit,hvdinit,hvon,hvoff
  42.     ext    gcomnam,comnam
  43.     ext    z3init,envptr,z3log,getcrt,puter2,inverror    ; Z3LIB
  44.     ext    isdigit,retud,initfcb,eval,padc,pa2hc,pafdc    ; SYSLIB
  45.     ext    caps,eprint,epstr,crlf,pfn2,cin,condin,cout
  46.     ext    codend
  47.     ext    plwdc                        ; ZSLIB 3.6
  48. ;
  49.     jp    Start
  50. ;
  51.     db    'Z3ENV',1
  52. Z3EAdr:    dw    0
  53. ;
  54. ; Configuration . . .
  55. ;
  56.     dw    0        ; filler
  57.     db    'CCOUNT'    ; for ZCNFG
  58.     db    Vers/10+'0',Vers mod 10+'0'
  59. AllFlg:    db    0        ; 0=requested matches, FFh=all matches
  60. HiFlg:    db    0        ; 0=ignore high bits, FFh=don't
  61. PagFlg:    db    0        ; 0=page screen, FFh=don't
  62. AbtFlg:    db    0        ; 0=abort no error, FFh=abort is error
  63. CRTLns:    db    24        ; number of lines on screen (CP/M only)
  64. ;
  65. ; Start of Program . . .
  66. ;
  67. Start:    ld    hl,(Z3EAdr)
  68.     call    zcheck        ; check for Z-System
  69.     jr    z,IsZ3        ; (it is)
  70.     ld    hl,0        ; it's not, so make ENVPTR zero
  71. IsZ3:    call    z3init        ; initialize ENVPTR
  72.     ld    (Stack),sp    ; save stack pointer
  73.     ld    sp,Stack    ; set up new stack
  74.     ld    hl,DftNam    ; point to default program name
  75.     call    gcomnam        ; get invocation name, if possible
  76.     call    hvtinit        ; initialize terminal
  77. ;
  78.     call    GetOpt        ; initialize data area, parse command line
  79.     call    IniFil        ; set up control block, log into directory
  80.     call    OpnFil        ; open file
  81.     call    RdLoop        ; process file byte by byte
  82.     call    ClsFil        ; close file
  83.     call    Report        ; print results
  84. ;
  85. Finish:    xor    a        ; no error
  86. ErExit:    ld    b,a        ; put error code in B
  87.     call    Z3Chk        ; Z-System?
  88.     jr    z,Exit        ; (no, so skip error flag)
  89.     ld    a,b        ; recover error code
  90.     call    puter2        ; load program error flag
  91.     or    a        ; error?
  92.     call    nz,inverror    ; (if so, invoke error handler)
  93. Exit:    call    hvdinit        ; de-initialize terminal
  94.     ld    sp,(Stack)    ; restore stack
  95.     ret            ; return to system
  96. ;
  97. ; Subroutines . . .
  98. ;
  99. ; GetOpt -- Initialize data area and parse command line parameters.
  100. ;
  101. GetOpt:    xor    a        ; initialize data segment to nulls
  102.     ld    (BegIni),a
  103.     ld    hl,BegIni
  104.     ld    de,BegIni+1
  105.     ld    bc,EndIni-BegIni
  106.     ldir
  107.     ld    hl,(HiFlg)    ; set default options
  108.     ld    (OpHFlg),hl
  109.     ld    a,(AllFlg)
  110.     ld    (OpAFlg),a
  111.     call    Z3Chk        ; Z-System?
  112.     ld    a,(CRTLns)    ; assume default screen lines
  113.     jr    z,GetOp1    ; (not Z3, use default)
  114.     call    getcrt        ; get screen lines from environment
  115.     inc    hl
  116.     ld    a,(hl)
  117. GetOp1:    dec    a        ; screen lines - 1
  118.     ld    (ScrLns),a    ; ..to permanent storage
  119.     dec    a        ; screen lines - 2 for first screen
  120.     ld    (LnsCnt),a    ; ..to screen lines counter
  121.     ld    hl,CpmDma+1    ; point to command tail
  122.     ld    a,1        ; check first token
  123.     push    hl        ; save CL pointer
  124.     call    parget        ; make sure we have a file spec
  125.     pop    hl        ; restore pointer
  126.     jp    z,Usage        ; (none, show how to use it)
  127.     cp    '/'        ; usage request?
  128.     jp    z,Usage        ; (yes)
  129.     ld    a,2        ; check second token
  130.     call    parget        ; do we have any search characters?
  131.     ret    z        ; (none)
  132.     cp    '/'        ; is the first character a slash?
  133.     jr    z,GotOp1    ; (yes, must be options)
  134.     ld    hl,CpmDma+1    ; point back to start of command line
  135.     ld    de,SchStr    ; point to search byte storage
  136.     ld    c,1        ; start with second token
  137. OpLoop:    inc    c        ; point to next token
  138.     ld    a,c        ; move token counter to A for PARGET
  139.     push    hl        ; save CL pointer
  140.     call    parget        ; get token
  141.     jr    z,PrsEnd    ; (end of command line)
  142.     cp    '"'        ; upper-case letter?
  143.     jr    z,AscChr    ; (yes)
  144.     cp    ''''        ; lower-case letter?
  145.     jr    z,AscLow    ; (yes)
  146.     cp    '^'        ; control character?
  147.     jr    z,AscCtl    ; (yes)
  148.     cp    '/'        ; option string?
  149.     jr    z,GotOpt    ; (must be)
  150.     call    isdigit        ; decimal or hex?
  151.     jr    nz,PrsErr    ; (nope, invalid parameter)
  152.     push    de        ; save storage pointer
  153.     call    eval        ; evaluate number
  154.     jr    c,PrsErr    ; (EVAL error)
  155.     ld    a,d        ; high byte zero?
  156.     or    a
  157.     jr    nz,PrsErr    ; (no, number too large)
  158.     dec    hl        ; prepare for ChkPrs
  159.     ld    a,e        ; get low byte from EVAL
  160.     pop    de        ; recover storage pointer
  161. OpLp1:    ld    (de),a        ; store converted parameter
  162.     inc    de        ; point to next open slot
  163.     call    ChkPrs        ; check for illegal trailing character
  164.     ld    hl,SchCnt    ; point to search byte counter
  165.     inc    (hl)        ; ..and increment it
  166.     pop    hl        ; recover CL pointer
  167.     jr    OpLoop        ; ..and continue with next token
  168. ;
  169. ; End of command line parse
  170. PrsEnd:    pop    hl        ; adjust stack and return
  171.     ret
  172. ;
  173. AscLow:    inc    hl        ; point to character after quote
  174.     ld    a,(hl)        ; get it
  175.     call    uncaps        ; make it lower-case
  176.     jr    OpLp1        ; store it and continue
  177. ;
  178. AscChr:    inc    hl        ; point to character after quote
  179.     ld    a,(hl)        ; get it
  180.     call    caps        ; make it upper-case
  181.     jr    OpLp1        ; store it and continue
  182. ;
  183. AscCtl:    inc    hl        ; point to character after caret
  184.     ld    a,(hl)        ; get it
  185.     sub    '@'        ; make it a control character
  186.     jr    nc,OpLp1    ; (if okay, store it and continue)
  187. ;
  188. ; Invalid command line parameter
  189. PrsErr:    ld    a,19        ; error code
  190.     call    eprint
  191.     db    'Invalid parameter.',0
  192.     jp    ErExit
  193. ;
  194. ; Parse command line options after slash
  195. GotOpt:    pop    de        ; adjust stack
  196. GotOp1:    inc    hl        ; point to next character
  197.     ld    a,(hl)        ; get it
  198.     or    a
  199.     ret    z        ; (zero is end of command line)
  200.     cp    'A'        ; count all characters?
  201.     jr    z,OptA
  202.     cp    'H'        ; make high bits significant?
  203.     jr    z,OptH
  204.     cp    'P'        ; page screen?
  205.     jr    z,OptP
  206.     cp    ' '        ; space?
  207.     jr    z,GotOp1    ; (skip intervening and trailing spaces)
  208.     ld    a,19        ; error code
  209.     call    eprint
  210.     db    'Invalid option.',0
  211.     jp    ErExit
  212. ;
  213. OptA:    ld    de,OpAFlg    ; point to option A flag
  214.     jr    DoOpt        ; ..flip it and continue
  215. ;
  216. OptH:    ld    de,OpHFlg    ; point to option H flag
  217. ;
  218. DoOpt:    ld    a,(de)        ; get flag
  219.     cpl            ; flip it
  220.     ld    (de),a        ; put it back
  221.     jr    GotOp1        ; get next option
  222. ;
  223. OptP:    ld    de,OpPFlg    ; point to option P flag
  224.     jr    DoOpt        ; ..flip it and continue
  225. ;
  226. ; ChkPrs -- Checks for illegal trailing character after parameter token
  227. ; is evaluated.
  228. ;
  229. ChkPrs:    inc    hl        ; get next character from command line
  230.     ld    a,(hl)
  231.     cp    ' '
  232.     ret    z        ; (okay)
  233.     cp    TAB
  234.     ret    z        ; (okay)
  235.     or    a
  236.     ret    z        ; (okay)
  237.     jr    PrsErr        ; otherwise, it's wrong
  238. ;
  239. ; IniFil -- Set up input control block, file control block, and buffers.
  240. ; Log into target directory.
  241. ;
  242. IniFil:    ld    hl,InFcb    ; HL -> control block FCB
  243.     ld    de,CpmFcb    ; DE -> default FCB
  244.     call    Z3Chk        ; Z-System?
  245.     jr    nz,IniFl1    ; (yep)
  246.     call    retud        ; for CP/M, get current user
  247.     ld    a,c
  248.     ld    (CpmFcb+13),a    ; ..and stuff it into FCB
  249. IniFl1:    call    z3log        ; log into directory
  250.     ex    de,hl
  251.     inc    hl        ; HL -> filename
  252.     ld    a,(hl)        ; anything there?
  253.     cp    ' '
  254.     jr    z,MissFn    ; (missing filename)
  255.     push    hl        ; save filename pointer
  256.     ld    bc,11
  257.     push    bc        ; save length count
  258.     ld    a,'?'        ; ambiguous?
  259.     cpir
  260.     jr    z,AmbgFn    ; (yep, can't do it)
  261.     inc    de        ; DE -> InFcb filename space
  262.     pop    bc        ; recover length count
  263.     pop    hl        ; recover filename pointer
  264.     ldir            ; move it
  265.     ld    a,BufSiz    ; put buffer size in input control block
  266.     ld    (InCtrl),a
  267.     call    codend
  268.     ld    (BufAdr),hl    ; put buffer address in input control block
  269.     ld    a,(CpmFcb+15)    ; check for invalid directory spec
  270.     inc    a
  271.     jr    nz,DirOK    ; (directory spec okay)
  272.     ld    a,2        ; error code
  273.     call    eprint
  274.     db    'Invalid directory.',0
  275.     jp    ErExit
  276. ;
  277. MissFn:    call    eprint
  278.     db    'Missing',0
  279.     jr    NamErr
  280. ;
  281. AmbgFn:    call    eprint
  282.     db    'Ambiguous',0
  283. NamErr:    call    eprint
  284.     db    ' filename.',0
  285.     ld    a,8        ; error code
  286.     jp    ErExit
  287. ;
  288. DirOK:    call    eprint
  289.     db    'Reading ',0
  290.     call    hvon        ; turn on highlighting
  291.     call    retud        ; get drive and user
  292.     ld    a,b        ; get drive
  293.     add    a,'A'        ; ..make it ASCII
  294.     call    cout        ; ..and print it
  295.     ld    a,c        ; get user
  296.     call    pafdc        ; ..and print it
  297.     ld    a,':'
  298.     call    cout        ; print colon
  299.     ld    de,InFcb+1    ; point to filename
  300.     call    pfn2        ; ..and print it
  301.     call    hvoff        ; turn off highlighting
  302.     call    eprint
  303.     db    ' .. ',0
  304.     ret
  305. ;
  306. ; OpnFil -- Open file for reading.
  307. ;
  308. OpnFil:    ld    de,InCtrl    ; point to input control block
  309.     call    fxropen        ; open file
  310.     ret    nz        ; (open okay)
  311.     ld    a,10        ; error code
  312.     call    eprint
  313.     db    'Not found.',0
  314.     jp    ErExit
  315. ;
  316. ; RdLoop -- Reads and processes characters from file according to user's
  317. ; selections.  Separate loops are provided for the four basic options
  318. ; in the interest of speed (since space is no problem).
  319. ;
  320. RdLoop:    ld    de,InCtrl    ; point to input control block
  321.     ld    a,(OpHFlg)    ; check H flag
  322.     or    a
  323.     jr    nz,RLoopH    ; (high bits are significant)
  324.     ld    a,(OpAFlg)    ; check A flag
  325.     or    a
  326.     jr    nz,ALoop    ; (count all characters)
  327. ;
  328. ; GLoop counts only given characters, ignoring high bits
  329. ;
  330. GLoop:    call    fxget        ; get character
  331.     ret    z        ; (end of file)
  332.     cp    CpmEof
  333.     jr    z,GotEof    ; (end of file)
  334.     and    7Fh        ; reset high bit
  335.     call    Match        ; check for match
  336.     jr    GLoop        ; get next character
  337. ;
  338. ; ALoop counts all characters, ignoring high bits
  339. ;
  340. ALoop:    call    fxget        ; get character
  341.     ret    z        ; (end of file)
  342.     cp    CpmEof
  343.     jr    z,GotEof    ; (end of file)
  344.     and    7Fh        ; reset high bit
  345.     call    CkCon        ; check for user abort
  346.     call    IncTot        ; increment total characters counter
  347.     call    GotMat        ; increment character array
  348.     jr    ALoop        ; get next character
  349. ;
  350. ; RLoopH -- high bits are significant here
  351. ;
  352. RLoopH:    ld    a,(OpAFlg)    ; check A flag
  353.     or    a
  354.     jr    nz,ALoopH    ; (count all characters)
  355. ;
  356. ; GLoopH counts only given characters, and high bits are significant
  357. ;
  358. GLoopH:    call    fxget        ; get character
  359.     ret    z        ; (end of file)
  360.     cp    CpmEof
  361.     jr    z,GotEof    ; (end of file)
  362.     call    Match        ; check for match
  363.     jr    GLoopH        ; get next character
  364. ;
  365. ; ALoopH counts all characters, and high bits are significant
  366. ;
  367. ALoopH:    call    fxget        ; get character
  368.     ret    z        ; (end of file)
  369.     cp    CpmEof
  370.     jr    z,GotEof    ; (end of file)
  371.     call    CkCon        ; check for user abort
  372.     call    IncTot        ; increment total characters counter
  373.     call    GotMat        ; increment character array
  374.     jr    ALoopH        ; get next character
  375. ;
  376. ; GotEof -- End-of-file character is recorded, but is not included
  377. ; in the total number of characters because it is not really part
  378. ; of the text.  Still, it's sometimes useful to know it's there.
  379. ;
  380. GotEof:    call    GotMat        ; record ^Z end-of-file character
  381.     ret            ; ..and quit
  382. ;
  383. ; Match -- Matches and counts characters for "given characters" loops
  384. ; (GLoop and GLoopH).  Must preserve DE.
  385. ;
  386. Match:    call    CkCon        ; check for user abort
  387.     call    IncTot        ; increment total characters counter
  388.     ld    hl,SchCnt    ; get number of search characters
  389.     ld    b,(hl)        ; ..into B
  390.     inc    b        ; check for zero
  391.     dec    b
  392.     ret    z        ; (no search characters)
  393.     ld    hl,SchStr-1    ; point to search characters string
  394. MLoop:    inc    hl        ; point to next search character
  395.     cp    (hl)        ; does it match our character in A?
  396.     jr    z,GotMat    ; (match found, increment character array)
  397.     djnz    MLoop        ; loop to end of search string
  398.     ret
  399. ;
  400. ; GotMat -- Computes address in 1024-byte array by using the value of
  401. ; the character in A.  Then the four-byte-long word at the computed
  402. ; address is incremented.  DE is preserved.
  403. ;
  404. GotMat:    ld    bc,CCount    ; get address of array
  405.     ld    l,a        ; compute offset into array
  406.     ld    h,0        ; ..using ASCII value of character
  407.     add    hl,hl        ; ASCII value times 2
  408.     add    hl,hl        ; ASCII value times 4
  409.     add    hl,bc        ; HL -> low byte of corresponding counter
  410. ;
  411. ; Incr32 -- increments 32-bit binary number (4 bytes, low-byte first)
  412. ; pointed to by HL.
  413. ;
  414. Incr32:    ld    b,4        ; 4 bytes
  415. Loop32:    inc    (hl)        ; increment byte
  416.     ret    nz        ; (quit if it hasn't reach zero)
  417.     inc    hl        ; point to next byte
  418.     djnz    Loop32        ; ..and do it again
  419.     ret
  420. ;
  421. IncTot:    ld    hl,ChrCnt
  422.     jr    Incr32
  423. ;
  424. ; ClsFil -- Closes input file.
  425. ;
  426. ClsFil:    ld    de,InCtrl    ; point to file control block
  427.     call    fxrclose    ; close file
  428.     ret    nz        ; (close okay)
  429.     ld    a,4        ; error code
  430.     call    eprint
  431.     db    'File close error.',0
  432.     jp    ErExit
  433. ;
  434. ; Report -- Prints summary report on console.
  435. ;
  436. Report:    call    crlf
  437.     ld    hl,ChrCnt    ; point to total of characters found
  438.     call    Prt32        ; and print it
  439.     call    eprint
  440.     db    '  ->  Total Characters',0
  441.     ld    a,(OpAFlg)
  442.     or    a
  443.     jr    z,ReptG        ; (only given characters)
  444. ;
  445. ; ReptA -- Report all characters in set.
  446. ;
  447. ReptA:    xor    a        ; characters from null to FFh
  448.     ld    c,a        ; duplicate character is kept in C
  449.     ld    b,a        ; 256 of them
  450. RALoop:    bit    7,c        ; 8-bit character?
  451.     jr    z,RALp1        ; (no)
  452.     ld    a,(OpHFlg)    ; yes, but are we ignoring them?
  453.     or    a
  454.     ret    z        ; (yes, so we're through)
  455.     ld    a,c        ; recover character
  456. RALp1:    call    PrtRep        ; report on this character
  457.     inc    c        ; increment both copies of character
  458.     inc    a
  459.     djnz    RALoop        ; loop through them all
  460.     ret
  461. ;
  462. ; ReptG -- Report counts only for characters given on command line
  463. ;
  464. ReptG:    ld    hl,SchCnt    ; point to number of search characters
  465.     inc    (hl)        ; check for zero
  466.     dec    (hl)
  467.     ret    z        ; (no search characters)
  468.     ld    b,(hl)        ; get number into counter
  469.     ld    hl,SchStr-1    ; point to search string
  470. ;
  471. RGLoop:    inc    hl        ; point to next search character
  472.     ld    a,(hl)        ; get it into A
  473.     ld    c,a        ; ..and a duplicate into C
  474.     bit    7,a        ; 8-bit character?
  475.     jr    z,RGLp1        ; (nope)
  476.     ld    a,(OpHFlg)    ; check H flag
  477.     or    a
  478.     ld    a,c        ; get character back into A
  479.     jr    z,RGLp2        ; (ignore 8-bit character)
  480. RGLp1:    call    PrtRep        ; report on this character
  481. RGLp2:    djnz    RGLoop        ; ..and continue
  482.     ret            ; done
  483. ;
  484. ; PrtRep -- Prints report of number found of character in A (also duplicated
  485. ; in C), followed by character value in ASCII, hexadecimal, and decimal.
  486. ;
  487. PrtRep:    push    af        ; save character
  488.     call    CkScrn        ; increment screen counter, check for pause
  489.     pop    af        ; restore character
  490.     call    PrtMat        ; print count
  491.     call    eprint
  492.     db    '  ->  ',0
  493.     push    hl        ; save SchStr pointer
  494.     call    PrtAsc        ; print ASCII value
  495.     bit    7,a        ; was a "+" printed?
  496.     call    z,Space1    ; (no, add extra space instead)
  497.     call    Space3
  498.     call    PrtHex        ; print hexadecimal value
  499.     call    Space3
  500.     call    PrtDec        ; print decimal value
  501.     pop    hl        ; recover SchStr pointer
  502.     ret
  503. ;
  504. ; PrtAsc -- Prints ASCII representation of value in A (duplicated in C),
  505. ; prefixing a "^" if a control character, suffixing a "+" if an 8-bit
  506. ; character, printing "SP" for space and "DL" for delete.  Preserves
  507. ; character in A and C.
  508. ;
  509. PrtAsc:    ld    c,a        ; save character in C
  510.     call    Space1
  511.     ld    a,(OpHFlg)    ; check H flag
  512.     or    a
  513.     ld    a,c        ; recover character
  514.     jr    z,PrtAs1    ; (we're ignoring high bits)
  515.     bit    7,a        ; check high bit
  516.     jr    nz,PrtHi    ; (special handling for 8-bit character)
  517. PrtAs1:    cp    7Fh        ; DEL?
  518.     jr    z,PrtDel    ; (yes, special handling)
  519.     cp    ' '        ; space?
  520.     jr    z,PrtSpc    ; (yes, special handling)
  521.     jr    c,PrtCtl    ; (control character, special handling)
  522.     call    Space1
  523.     ld    a,c        ; get new copy in A
  524.     call    cout        ; ..and print it
  525.     ret
  526. ;
  527. ; PrtCtl -- Special handling for control characters
  528. PrtCtl:    ld    a,'^'
  529.     call    cout        ; print caret
  530.     ld    a,c
  531.     add    a,'@'        ; make character printable
  532.     call    cout        ; ..and print it
  533.     ld    a,c        ; restore character
  534.     ret
  535. ;
  536. ; PrtSpc -- Special handling for space character
  537. PrtSpc:    call    eprint        ; print "SP"
  538.     db    'SP',0
  539.     ld    a,c        ; restore character
  540.     ret
  541. ;
  542. ; PrtDel -- Special handling for DEL character
  543. PrtDel:    call    eprint        ; print "DL"
  544.     db    'DL',0
  545.     ld    a,c        ; restore character
  546.     ret
  547. ;
  548. ; PrtHi -- Special handling for 8-bit characters
  549. PrtHi:    push    af        ; save character
  550.     and    7Fh        ; reset high bit
  551.     ld    c,a        ; put copy in C
  552.     call    PrtAs1        ; print it
  553.     ld    a,'+'
  554.     call    cout        ; suffix it with a "+"
  555.     pop    af        ; recover character
  556.     ret
  557. ;
  558. ; PrtDec -- Prints decimal value of character in A in three-character field.
  559. ;
  560. PrtDec:    call padc
  561.     ret
  562. ;
  563. ; PrtHex -- Prints two-character hexadecimal value of character in A,
  564. ; suffixing an "h".
  565. ;
  566. PrtHex:    call    pa2hc        ; print value
  567.     push    af        ; save character
  568.     ld    a,'h'
  569.     call    cout        ; suffix an "h"
  570.     pop    af        ; recover character
  571.     ret
  572. ;
  573. ; Prt32 -- Prints 32-bit number pointed to by HL.  Preserves AF and BC.
  574. ;
  575. Prt32:    push    af        ; save character
  576.     ld    a,NumSiz    ; field size
  577.     call    plwdc        ; convert binary to ASCII string
  578.     pop    af        ; restore character
  579.     ret
  580. ;
  581. ; Space1, Space2, Space3 -- Prints corresponding number of spaces on
  582. ; the console, preserving all registers.
  583. ;
  584. Space3:    call    Space1
  585. Space2:    call    Space1
  586. Space1:    push    af
  587.     ld    a,' '
  588.     call    cout
  589.     pop    af
  590.     ret
  591. ;
  592. ; PrtMat -- retrieves character count from array of 32-bit counters,
  593. ; and prints it.  Preserves A, BC, and HL.
  594. ;
  595. PrtMat:    push    hl        ; save HL
  596.     ld    de,CCount    ; point to array
  597.     ld    l,a        ; compute offset into array
  598.     ld    h,0        ; ..using ASCII value of character
  599.     add    hl,hl        ; ASCII value times 2
  600.     add    hl,hl        ; ASCII value times 4
  601.     add    hl,de        ; HL -> low byte of corresponding counter
  602.     call    Prt32        ; print count
  603.     pop    hl        ; recover HL
  604.     ret
  605. ;
  606. ; Z3Chk -- confirms Z-System by checking ENVPTR.  Returns Z if not ZCPR3.
  607. ;
  608. Z3Chk:    ld    a,(envptr+1)    ; get high byte of pointer
  609.     or    a        ; zero means no Z3
  610.     ret
  611. ;
  612. ; CkScrn -- Increments and checks screen lines counter.  Monitors for
  613. ; user input via CkAbrt.
  614. ;
  615. CkScrn:    call    CkAbrt        ; check for user input
  616.     ld    a,(OpPFlg)    ; check P flag
  617.     or    a
  618.     call    nz,crlf        ; (new line if no screen paging)
  619.     ret    nz        ; (no paging)
  620.     ld    a,(LnsCnt)    ; get line counter
  621.     dec    a        ; ..decrement it
  622.     ld    (LnsCnt),a    ; ..and put it back
  623.     call    nz,crlf        ; (new line if screen not filled)
  624.     ret    nz        ; (screen not filled)
  625.     call    eprint        ; screen is filled, print "[more]"
  626.     db    CR,LF
  627.     db    '[more]',0
  628.     call    cin        ; ..and pause for user to press a key
  629.     call    eprint        ; key pressed, erase "[more]"
  630.     db    CR,'      ',CR,0
  631.     cp    CtrlC        ; was the key ^C?
  632.     jr    z,Abort        ; (yes, abort the program)
  633.     cp    ' '        ; was the key a space?
  634.     ld    a,1        ; assume it was
  635.     ld    (LnsCnt),a
  636.     ret    z        ; (it was, so advance by one line)
  637.     ld    a,(ScrLns)    ; otherwise, fill the screen again
  638.     ld    (LnsCnt),a
  639.     ret
  640. ;
  641. ; CkCon -- Checks for user input at the end of each line, while file is
  642. ; being read.  Aborts program if ^C is received.
  643. ;
  644. CkCon:    cp    LF        ; line feed?
  645.     ret    nz        ; (not end of line)
  646.     push    af        ; save character
  647.     call    condin        ; check console
  648.     cp    CtrlC        ; ^C?
  649.     jr    z,CkCon1    ; (yep, abort)
  650.     pop    af        ; recover character
  651.     ret
  652. ;
  653. CkCon1:    pop    af        ; adjust stack
  654.     call    ClsFil        ; close file
  655.     jr    Abort        ; ..and abort
  656. ;
  657. ; CkAbrt -- Checks for user input.  If ^S, wait for another key before
  658. ; continuing.  If ^C, abort the program.  If anything else, ignore it.
  659. ;
  660. CkAbrt:    call    condin        ; check for key press
  661.     ret    z        ; (none, continue)
  662.     cp    CtrlS        ; ^S?
  663.     call    z,cin        ; (yes, wait for another key)
  664.     cp    CtrlC        ; ^C?
  665.     ret    nz        ; (no, continue)
  666.     call    crlf        ; yes, send new line and abort
  667. ;
  668. ; Abort -- abort to operating system.  Set error flag according to
  669. ; configuration.
  670. ;
  671. Abort:    ld    a,(AbtFlg)    ; error code (if any)
  672.     call    eprint
  673.     db    'Aborted',0
  674.     jp    ErExit
  675. ;
  676. ; Usage -- intelligent usage screen
  677. ;
  678. Usage:    call    eprint
  679. DftNam:    db    'CCOUNT    Version '
  680.     db    Vers/10+'0','.',Vers mod 10+'0',SubVers,CR,LF
  681.     db    'Counts characters in text files.',CR,LF
  682.     db    'Usage:',CR,LF,'   ',0
  683.     ld    hl,comnam
  684.     call    epstr        ; print invocation or default name
  685.     call    eprint
  686.     db    ' {dir:}infile {byte {...}} {/options}',CR,LF
  687.     db    'Options:',CR,LF
  688.     db    '   A   count ',0
  689.     ld    a,(AllFlg)    ; check configuration flag
  690.     or    a
  691.     ld    hl,MsgAll
  692.     jr    z,Usage1
  693.     ld    hl,MsgGiv
  694. Usage1:    call    epstr
  695.     call    eprint
  696.     db    ' characters',CR,LF
  697.     db    '   H   high bits are ',0
  698.     ld    a,(HiFlg)    ; check configuration flag
  699.     or    a
  700.     call    nz,PrtIn
  701.     call    eprint
  702.     db    'significant',CR,LF
  703.     db    '   P   ',0
  704.     ld    a,(PagFlg)    ; check configuration flag
  705.     or    a
  706.     call    z,PrDont
  707.     call    eprint
  708.     db    'page screen',CR,LF
  709.     db    'Bytes:',CR,LF
  710.     db    '  ''c   lower-case character',CR,LF
  711.     db    '  "c   upper-case character',CR,LF
  712.     db    '  ^c   control character',CR,LF
  713.     db    '  nn   decimal ASCII value',CR,LF
  714.     db    ' nnH   hexadecimal ASCII value',CR,LF
  715.     db    'Hexadecimal values must begin with a digit.',0
  716.     jp    Finish
  717. ;
  718. MsgAll:    db    'all',0
  719. MsgGiv:    db    'given',0
  720. ;
  721. PrtIn:    call    eprint
  722.     db    'in',0
  723.     ret
  724. ;
  725. PrDont:    call    eprint
  726.     db    'don''t ',0
  727.     ret
  728. ;
  729.     DSEG
  730. ;
  731. ScrLns:    ds    1        ; number of screen lines
  732. LnsCnt:    ds    1        ; screen lines counter
  733. OpAFlg:    ds    1        ; FFh=display all characters
  734. OpHFlg:    ds    1        ; 0=ignore high bits
  735. OpPFlg:    ds    1        ; 0=page screen
  736. BegIni    equ    $        ; beginning of data initialization area
  737. SchCnt:    ds    1        ; number of characters we're counting
  738. SchStr:    ds    65        ; string of bytes to match and count
  739. ChrCnt:    ds    4        ; total characters found
  740. CCount:    ds    256*4        ; character count table (256 * 4 bytes)
  741. InCtrl:    ds    1        ; control table for input file
  742.     ds    7
  743. BufAdr:    ds    2
  744. InFcb:    ds    36
  745. EndIni    equ    $        ; end of data initialization area
  746. ;
  747.     ds    100        ; stack
  748. Stack:    ds    2        ; stack pointer storage
  749. ;
  750.     end
  751.