home *** CD-ROM | disk | FTP | other *** search
/ CP/M / CPM_CDROM.iso / cpm / utils / asmutl / xref36.lbr / XREF36.AZM / XREF36.ASM
Encoding:
Assembly Source File  |  1987-08-25  |  70.0 KB  |  3,210 lines

  1.     title    'XREF v3.06 - Assembler cross reference utility            83/10/18, 01:28'
  2.  
  3. vers    equ    3
  4. revs    equ    6
  5.  
  6. *************************************************************************
  7. *                                    *
  8. *          Macro Assembler Cross Reference Program            *
  9. *                                    *
  10. *   Program: XREF36.ASM                            *
  11. *   By:         Lucien Pan     Toronto, Ontario, Canada  (416) 690-8068 [h]    *
  12. *                                    *
  13. *   Copyright  (c)  1983 by Lucien Pan.     All  rights  reserved.     This    *
  14. *   public domain program is distributed for non-commercial use    only.    *
  15. *   The    author assumes no responsibility or liability for it's use.    *
  16. *                                    *
  17. *************************************************************************
  18.  
  19. *************************************************************************
  20. *                                    *
  21. *   REVISION LOG:                            *
  22. *   ------------                            *
  23. *                                    *
  24. *   83/10/17 Added   disk  file     output     (forced  to   fn.LST),      tab    *
  25. *    v3.06   expansion/compression   routines    to  conserve   space,    *
  26. *         improved report by    automatically executing    a second pass    *
  27. *         through  the  file,  this time listing  only  the    lines    *
  28. *         containing     errors,  tracing the progression on the CON:    *
  29. *         in     the  form of pass/line    number or actual  file    being    *
  30. *         parsed  and finally the ability to    list only  the    error    *
  31. *         lines  in a file or get a summary report which  contains    *
  32. *         the  symbol table (if any),  the cross-reference listing    *
  33. *         and the error lines (if any).  All    these and a few    other    *
  34. *         options are selectable at run-time.            *
  35. *                        - LLP.            *
  36. *                                    *
  37. *   83/09/14 This one was long due.  Adapted program to    accept    TDL's    *
  38. *    v3.05   macro  assembler .PRN listing file.  This utility is now    *
  39. *         slightly  more  refined.  Because MACROII    (TM  Computer    *
  40. *         Design   Labs.)  does not use  form-feeds,     it  must  be    *
  41. *         patched to    enable    XREF to    bypass the header;  following    *
  42. *         is    a simple procedure to do so:                *
  43. *                                    *
  44. *        A>DDT (or ZSID)                        *
  45. *        -F100 5000 0                        *
  46. *        -IMACROII.COM                        *
  47. *        -R                            *
  48. *        NEXT PC                            *
  49. *        3900 0100                        *
  50. *        -S509                            *
  51. *        0509 0D    8D                        *
  52. *        050A 0A    01                        *
  53. *        050B 43    .                        *
  54. *        -^C                            *
  55. *                                    *
  56. *        A>SAVE 47 (anyname you whish).COM            *
  57. *                                    *
  58. *         We     simply    set the    8th bit    on the header initial CR  and    *
  59. *         replaced  the  following LF by a dummy character  (don't    *
  60. *         use @NUL or @CR).    Either version may be assembled     from    *
  61. *         the  same    source file simply by setting the TDL  symbol    *
  62. *         equate to true or false.                    *
  63. *                        - LLP.            *
  64. *                                    *
  65. *   83/06/20 Improved  listing    appearance by flagging    error    lines    *
  66. *    v3.04   with  '***'.  Also     added    statistics report at  end  of    *
  67. *         XREF.                            *
  68. *                        - LLP.            *
  69. *                                    *
  70. *   83/06/14 Fixed a bug occuring when no symbols were defined    in  a    *
  71. *    v3.03   program.  No  longer  needs title info or    page  preset.    *
  72. *         Symbol size increased to 7    characters.            *
  73. *                        - LLP.            *
  74. *                                    *
  75. *   83/06/03 Improved  error handling routines,     adapted program   to    *
  76. *    v3.02   accept  files generated by    "ASM" (of Digital  Research),    *
  77. *         cleaned up    line printing routine.                *
  78. *                        - LLP.            *
  79. *                                    *
  80. *   83/05/30 Fixed a bug clobbering line numbering and    printing when    *
  81. *    v3.01   an    macro expansion    was encountered.  (ex:    mac  filename    *
  82. *         $pc+smld)                            *
  83. *                        - LLP.            *
  84. *                                    *
  85. *=======================================================================*
  86. *                                    *
  87. *   ABSTRACT:                                *
  88. *   --------                                *
  89. *                                    *
  90. *      This  program will generate a  "bannered",  cross-referenced     *
  91. *   listing  of an .PRN file created by either DIGITAL RESEARCH's MAC     *
  92. *   or  COMPUTER  DESIGN LAB's (TDL)  MACROII  macro-assembler.  This     *
  93. *   feature is an assembly time option however.                *
  94. *                                    *
  95. *     Please     report    any bugs and/or    comments either     through  the    *
  96. *   TORONTO  RCP/M  SYSTEM ONE at (416)    231-0442 by leaving a message    *
  97. *   if    not too     impractical or    feel free to contact me     directly  by    *
  98. *   voice.                                *
  99. *                        - LLP.            *
  100. *                                    *
  101. *=======================================================================*
  102. *                                    *
  103. *   HISTORY:            v3.00                    *
  104. *   -------                                *
  105. *                                    *
  106. *     Based    on XREF.ASM,  originally written by Jeff Kravitz  and    *
  107. *   modified  by  P.P.H.  Lee,    Ward Christensen and others,  and  on    *
  108. *   BANNER.ASM,     modified by Ron Booley,  I integrated both  programs    *
  109. *   into one module and    adapted    it to accept .PRN files     from MAC.    *
  110. *                                    *
  111. *     Following is a    short description of some of the new features    *
  112. *   added:                                *
  113. *                                    *
  114. *     -    For the    sake of    "pretty-printing", a banner of the  file name    *
  115. *    information is generated at the    beginning of the  listing (in    *
  116. *    an  7X7     matrix     per character expanded)  for  easy   program    *
  117. *    identification when multiple listings are bound     together.  I    *
  118. *    suggest     that  the  first  page    be folded in  half  as     this    *
  119. *    procedure allows easy indexing through each of the  programs.    *
  120. *                                    *
  121. *     -    The  line identification number    is now appearing   after  the    *
  122. *    object    expansion  making  the final listing  more   readable    *
  123. *    especially when    a label    is printed right after the  expansion    *
  124. *    without    space in between as it is the case when     more than  5    *
  125. *    characters are being defined in    an labeled DB  statement.    *
  126. *                                    *
  127. *     -    In case    the file type is not specified,     the  default .PRN is    *
  128. *    assumed.                            *
  129. *                                    *
  130. *     -    The  symbol  length is now increased from 5 to 6   characters    *
  131. *    which I    believe    is enough for significant but "to  the point"    *
  132. *    names.                                *
  133. *                                    *
  134. *                        - Lucien L.    Pan, 83/05/22    *
  135. *                                    *
  136. *************************************************************************
  137.  
  138. false    equ    0        ;define boolean
  139. true    equ    not false    ;__equates
  140. debug    equ    false        ;debug version (save a tree)
  141. cpm22    equ    true        ;for standard CP/M 2.2 BDOS
  142. h19    equ    true        ;Heath/Zenith H-19 type terminal
  143. z8911    equ    false        ;use internal line printer device driver
  144.                 ;__because Magnolia's CP/M bios doesn't
  145.                 ;__support parallel i/o. Set to false to
  146.                 ;__use standard CP/M LST logical device
  147. eject    equ    false        ;no initial page form feed
  148. tdl    equ    true        ;Set to true or false
  149. mac    equ    not tdl        ;don't touch (set by above)
  150.  
  151. ;/******************************/
  152. ;
  153. ;   operating system equates
  154. ;
  155. ;/******************************/
  156.  
  157. ;   page zero addresses
  158.  
  159. base    equ    0        ;standard zero base CP/M
  160. wboot    equ    base        ;warm boot entry point
  161. bdos    equ    wboot+5        ;bdos entry point
  162. fbase    equ    wboot+6        ;highest user memory+1
  163. fcb    equ    wboot+5ch    ;default file control block
  164. fcb2    equ    wboot+6ch    ;second fcb
  165. dma    equ    wboot+80h    ;default dma address
  166. tpa    equ    wboot+100h    ;transient program area
  167.  
  168. ;   bdos functions parameters
  169.  
  170. conif    equ    1        ;console input
  171. conof    equ    2        ;console output
  172. listf    equ    5        ;list output
  173. dciof    equ    6        ;direct console i/o
  174. psbf    equ    9        ;print string buffer
  175. constf    equ    11        ;console status
  176. cpmver    equ    12        ;return version no.
  177. openf    equ    15        ;open file
  178. findf    equ    17        ;search file in directory
  179. closef    equ    16        ;close file
  180. deletf    equ    19        ;delete file
  181. readf    equ    20        ;read file
  182. writef    equ    21        ;write sequential file
  183. makef    equ    22        ;create file
  184. sdmaf    equ    26        ;set dma address
  185.  
  186. ;   misc system equates
  187.  
  188. fcbl    equ    36        ;length of fcb
  189. eof    equ    1ah        ;CP/M's end of file delimiter
  190.  
  191. ;/******************************/
  192. ;
  193. ;   ascii characters equates
  194. ;
  195. ;/******************************/
  196.  
  197. @nul    equ    '@'-40h        ;^@ (ascii null)
  198. @bel    equ    'G'-40h        ;^G (ascii bell)
  199. @tab    equ    'I'-40h        ;^I (ascii tab)
  200. @lf    equ    'J'-40h        ;^J (ascii line feed)
  201. @ff    equ    'L'-40h        ;^L (ascii form feed)
  202. @cr    equ    'M'-40h        ;^M (ascii carriage return)
  203. @esc    equ    '['-40h        ;^[ (ascii escape)
  204.  
  205. ;/******************************/
  206. ;
  207. ;   operational equates
  208. ;
  209. ;/******************************/
  210.  
  211. rsiz    equ    6        ;size of reserved word table entry
  212. symsiz    equ    7        ;max size of symbol
  213. ssiz    equ    symsiz+3    ;# of xref addresses by line
  214. refsz    equ    2+(ssiz*2)    ;# of bytes in ref. block
  215. tbsze    equ    20h        ;# of sectors to read to fill buffer
  216.  
  217.     if    mac
  218. pglen    equ    58        ;# of lines to be printed per page
  219.     endif            ;mac
  220.  
  221.     if    tdl
  222. pglen    equ    60
  223.     endif
  224.  
  225. digits    equ    5        ;# of digits for line number id.
  226.  
  227. ;/******************************/
  228. ;
  229. ;   program start
  230. ;
  231. ;/******************************/
  232.  
  233.     org    tpa
  234.  
  235.     jmp    xref        ;bypass header
  236.     db    'Copyright (C) 1983 by Lucien Pan'
  237. hello:    call    cdisp        ;identify oneself
  238.     db    'XREF v'
  239.     db    (vers mod 10)+'0','.'
  240.     db    revs/10+'0',(revs mod 10)+'0'
  241.  
  242.     if    z8911
  243.     db    'p'
  244.     endif
  245.     
  246.     db    ' for '
  247.  
  248.     if    mac
  249.     db    'MAC, ASM'
  250.     endif
  251.  
  252.     if    tdl
  253.     db    'TDL'
  254.     endif
  255.  
  256.     db    ' mnemonics.'
  257.  
  258.     if    h19
  259.     db    @esc,'x5'    ;disable cursor
  260.     endif            ;h19
  261.  
  262.     db    @cr,@lf,@nul
  263.     ret
  264.  
  265. xref:    lxi    h,0
  266.     dad    sp        ;get ccp stack in hl
  267.     lxi    sp,stack    ;set local stack pointer
  268.     push    h        ;save ccp stack ^ on local stack
  269.  
  270.     if    z8911
  271.     call    in8255        ;initialize parallel port
  272.     endif            ;z8911
  273.  
  274.     call    hello        ;say hello
  275.     call    setup        ;initialize program
  276. xref0:    call    cdisp
  277.  
  278.     if    h19
  279.     db    @esc,'l',@nul    ;HEL - erase entire line
  280.     else
  281.     db    '                          ',@nul
  282.     endif            ;h19
  283.  
  284.     call    getbt        ;get first byte of source file
  285.     cpi    eof
  286.     jz    empty        ;in case of eof
  287.     push    psw
  288.     call    ckerr        ;error only option selected?
  289.     jz    xref01        ;if not
  290.     sub    a        ;else, select pass two
  291.     sta    pass
  292.     lxi    h,done3        ;where to go when done
  293.     shld    way
  294. xref01:    pop    psw
  295.  
  296.     if    mac
  297.     cpi    ' '
  298.     jz    xref2        ;if case 'page 0' from "MAC"
  299.     cpi    @ff        ;bypass first form feed (from "MAC")
  300.     jz    xref2        ;process form feed case if so
  301.     cpi    @cr        ;bypass CR,LF,CR,LF sequence (from "ASM")
  302.     mvi    b,3
  303.     jz    xref1        ;if first char was indeed a @cr
  304.     call    ckalp        ;none of the above, char MUST at least be
  305.     jnc    xref2        ;__alphabetic (error code) to qualify as .PRN
  306.     jmp    former        ;in case an object file was requested
  307. xref1:    call    getbt        ;skip over "ASM" prologue
  308.     dcr    b
  309.     jnz    xref1
  310.     cpi    @lf        ;just to make sure
  311.     jnz    former        ;sorry!
  312.     endif            ;mac
  313.  
  314. xref2:    sta    char        ;save character for later use
  315.     call    ckpass        ;are we in pass 1 or 2?
  316.     jz    xref21        ;if pass two
  317.     call    cksumo        ;is summary option active?
  318.     jz    xref20        ;if not
  319.     sub    a        ;else, temporarily disable flag
  320.     sta    summary
  321.     call    banner        ;to print expanded file name
  322.     mvi    a,true        ;re-activate flag
  323.     sta    summary
  324.     ora    a
  325. xref20:    cz    banner        ;print expanded fcb information
  326. xref21:    lda    char        ;get back character
  327.  
  328.     if    mac
  329.     cpi    @lf        ;was it .PRN from "ASM"?
  330.     jz    llf0        ;if yes, process @lf case
  331.     cpi    @ff        ;was it .PRN from "MAC"?
  332.     jnz    xref3        ;if not
  333.     call    getfc        ;test for normal case
  334.     jz    llf1        ;parse if so
  335.     jmp    lff2        ;must be header case, process
  336. xref3:    call    savbt        ;save character in line buffer
  337.     cpi    ' '        ;was it .PRN from "MAC" w/page set at 0 ?
  338.     jz    llf1        ;continue parsing object expansion field
  339.     mvi    b,15        ;this is a long shot to help cluts
  340.     jmp    llf4        ;recover from an error in the very first line!
  341.     endif            ;mac
  342.  
  343.     if    tdl
  344.     cpi    @CR
  345.     jnz    former
  346. xref4:    call    skipnl        ;skip formatting new lines
  347.     call    ckban        ;if no banner wanted
  348.     jnz    xref41        ;__bypass initial form-feed
  349.     call    ckpass
  350.     cnz    formf
  351. xref41:    sub    a        ;clear this option flag
  352.     sta    nobanr        ;__for next iteration
  353.     call    header
  354.     jmp    main1
  355.     endif            ;tdl
  356.  
  357. ;/******************************/
  358. ;
  359. ;   character parsing mainline
  360. ;
  361. ;/******************************/
  362.  
  363. main:    call    getfc        ;get a byte from source file
  364. main1:    call    ckpass        ;is it pass 1 or 2?
  365.     lda    char
  366.     jz    main2        ;if pass 2
  367.     call    cknum        ;test for numeric
  368.     jnc    lnum        ;yes, found a number, process
  369.     call    ckalp        ;test for alphabetic
  370.     jnc    lalph        ;yes, process
  371. main2:    call    ckspc        ;parse special characters
  372.     jc    main        ;if not found, ignore and loop for more
  373.     pchl            ;when found, process special character
  374.  
  375. ;/******************************/
  376. ;
  377. ;   exit from program
  378. ;
  379. ;/******************************/
  380.  
  381. empty:    call    fcdisp
  382.     db    '+++ Unexpected end of file??? +++',@cr,@lf,@nul
  383.     jmp    exit
  384.  
  385. abort:    call    fcdisp
  386.     db    '+++ Aborted +++',@cr,@lf,@nul
  387. ;    jmp    exit
  388.  
  389. exit:    lxi    d,fcb        ;close source file
  390.     call    fclose
  391. exit1:
  392.     if    h19
  393.     call    fcdisp
  394.     db    @esc,'y5',@nul    ;re-enable cursor
  395.     endif            ;h19
  396.  
  397.     lxi    sp,stack-2    ;^ to old (ccp's) stack
  398.     pop    h        ;restore ccp stack
  399.     sphl
  400.     ret            ;return control back to CP/M
  401.  
  402. ;/******************************/
  403. ;
  404. ;   final statistics print
  405. ;
  406. ;/******************************/
  407.  
  408. done:    lxi    sp,stack-2    ;just to be safe
  409.     call    formf        ;issue formf eject
  410.     call    cdisp
  411.     db    @cr,'Listing cross-reference ',@cr,@nul
  412.     sta    pass        ;activate pass two flag
  413.     lhld    symbt        ;get symbol table bottom
  414.     call    endoft        ;test for no symbol case
  415.     jnz    done0        ;continue if symbol exist
  416.     call    lcdisp        ;else print warning
  417.     db    @bel,'+++ no symbol detected +++',@lf,@cr,@nul
  418.     jmp    done2        ;terminate program
  419. done0:    shld    sym        ;set symbol pointer
  420.     lhld    symtp        ;get symbol table top
  421.     mvi    m,-1        ;end off symbol table
  422. done1:    lhld    sym        ;get symbol table pointer
  423.     call    psym        ;print symbol
  424.     lhld    sym
  425.     lxi    d,symsiz+1    ;offset to ref link
  426.     dad    d
  427.     mov    e,m
  428.     inx    h
  429.     mov    d,m        ;get ref block addr
  430.     xchg            ;into hl
  431.     shld    ref
  432.     call    prefs        ;print references
  433.     lhld    sym        ;get symbol table pointer
  434.     lxi    d,ssiz        ;size of sym table entry
  435.     dad    d
  436.     shld    sym
  437.     call    endoft        ;test for end of table
  438.     jnz    done1        ;loop if not
  439. done2:    lhld    errorc        ;any errors detected?
  440.     mov    a,h
  441.     ora    l
  442.     jz    done4        ;if not, proceed with stats.
  443.  
  444. ;   errors were logged, scan file a second time
  445. ;   printing only error lines.
  446.  
  447.     lxi    h,done3        ;where to branch when eof hit
  448.     shld    way
  449.     call    formf        ;prettyprint
  450.     lxi    d,fcb        ;close and reopen file
  451.     call    fclose
  452.     lxi    d,ifcb
  453.     lxi    h,fcb
  454.     mvi    b,fcbl
  455.     call    move
  456.     lxi    d,fcb
  457.     call    fopen
  458.     jc    abort        ;in case murphy's around
  459.     call    initp
  460.     jmp    xref0        ;re-enter main loop
  461. done3:    call    crlf2
  462.     call    lptab
  463.     lhld    errorc
  464.     mov    a,h
  465.     ora    l
  466.     jnz    done31
  467.     call    ldisp
  468.     db    '   ',@nul
  469.     call    lcdisp
  470.     db    'No',@nul
  471. done31:    cnz    done7
  472.     call    lcdisp
  473.     db    ' error(s) detected        ',@lf,@cr,@nul
  474. done4:    call    crlft
  475.     call    lptab
  476.     lhld    lcnt
  477.     mov    a,h
  478.     ora    l
  479.     jz    exit
  480.  
  481.     if mac
  482.     dcx    h
  483.     endif
  484.  
  485.     call    done7
  486.     call    lcdisp
  487.     db    ' line(s) processed        ',@lf,@cr,@nul
  488.     call    formf
  489. done5:    call    ckdsk
  490.     jz    done6
  491.     mvi    a,eof        ;save end of file marker
  492.     call    putfc
  493.     lxi    d,dfcb        ;close destination file
  494.     call    fclose
  495.     inr    a        ;everything okay?
  496.     jnz    done6        ;if yes
  497.     call    fcdisp
  498.     db    @bel,' Is disk write protected? ',@nul
  499.     jmp    abort
  500. done6:    call    cdisp
  501.     db    'Cross-reference completed',@cr,@lf,@nul
  502.     jmp    exit        ;return to ccp
  503.  
  504. done7:    call    decout
  505.     jmp    prdec
  506.  
  507. ;/******************************/
  508. ;
  509. ;   symbol print routine
  510. ;
  511. ;/******************************/
  512.  
  513. psym:    mvi    b,symsiz    ;symbol size
  514.  
  515.     if    tdl        ;print a space after 6 chars
  516.     mvi    c,6        ;__to enhance truncated symbols
  517.     endif            ;tdl
  518.  
  519. psym0:    mov    e,m        ;get byte
  520.     call    pbyt        ;print byte
  521.     inx    h
  522.  
  523.     if    tdl
  524.     dcr    c
  525.     cz    psym1
  526.     endif            ;tdl
  527.  
  528.     dcr    b
  529.     jnz    psym0
  530. psym1:    mvi    e,' '
  531.  
  532.     if    mac        ;because enhanced printing
  533.     call    pbyt        ;__is only available on TDL
  534.     endif            ;mac
  535.  
  536.     jmp    pbyt        ;return through pbyt
  537.  
  538. ;/******************************/
  539. ;
  540. ;   reference print routine
  541. ;
  542. ;/******************************/
  543.  
  544. prefs:    lhld    ref        ;get ref block addr
  545.     inx    h
  546.     inx    h        ;bump to first ref number
  547.     shld    temp        ;save ref num addr
  548.     mvi    a,(refsz-2)/2    ;number of ref slots
  549.     sta    symct        ;save in symct
  550. pref:    mvi    e,' '
  551.     call    pbyt
  552.     lhld    temp        ;get ref slot addr
  553.     mov    e,m
  554.     inx    h
  555.     mov    d,m        ;get ref
  556.     lxi    h,0        ;zero?
  557.     call    cphl
  558.     jz    crlft        ;yes, done
  559.     xchg            ;get num in hl
  560.     call    decot        ;convert
  561.     lxi    h,dec        ;point to dec string
  562.     mvi    m,' '        ;blank leading zero
  563.     mvi    b,digits    ;set loop count
  564. pref2:    mov    e,m        ;get byte
  565.     call    pbyt        ;print byte
  566.     inx    h
  567.     dcr    b
  568.     jnz    pref2        ;print reference number
  569.     lhld    temp        ;get ref slot addr
  570.     inx    h
  571.     inx    h        ;bump to next slot
  572.     shld    temp
  573.     lda    symct        ;get count
  574.     dcr    a        ;decrement
  575.     sta    symct
  576.     jnz    pref
  577.     lhld    ref        ;get ref block address
  578.     mov    e,m
  579.     inx    h
  580.     mov    d,m        ;get link to next block
  581.     lxi    h,0
  582.     call    cphl        ;any more blocks?
  583.     jz    crlft        ;no, exit
  584.     xchg            ;yes, set next block pointer in ref
  585.     shld    ref
  586.     call    crlft        ;print cr,lf
  587.     mvi    b,symsiz+2
  588. pref3:    mvi    e,' '
  589.     call    pbyt        ;print spaces
  590.     dcr    b
  591.     jnz    pref3
  592.     jmp    prefs
  593.  
  594. ;/******************************/
  595. ;
  596. ;   character parsing routines
  597. ;
  598. ;/******************************/
  599.  
  600. lalph:    call    ckpass        ;don't xref on 2nd pass
  601.     jz    main
  602.     call    linit
  603.     call    gtsym        ;collect identifier
  604. lalph0:    call    getfc        ;get a byte from source file
  605.  
  606.     if    mac
  607.     cpi    '$'        ;'$' case?
  608.     jz    lalph0        ;if so, ignore
  609.     endif            ;mac
  610.  
  611. lalph1:    call    ckspsy        ;check for special symbol char
  612.     jz    lalph5
  613.     call    cknum        ;test for number
  614.     jnc    lalph5        ;yes, continue
  615.     call    ckalp        ;test for alphabetic
  616.     jnc    lalph5        ;yes, continue
  617.     call    cres        ;test for reserved word
  618.     jc    lalph3        ;no, continue
  619. lalph2:    lda    char        ;get character that ended id
  620.     jmp    main1        ;continue scan
  621. lalph3:    call    find        ;see if defined
  622.     jc    lalph4        ;no, continue
  623.     call    addrf        ;yes, add reference
  624.     jmp    lalph2        ;done
  625. lalph4:    call    ensym        ;enter symbol definition
  626.     call    addrf        ;add reference
  627.     jmp    lalph2        ;continue
  628. lalph5:    call    gtsym        ;collect identifier
  629.     jmp    lalph0        ;continue
  630.  
  631. lnum:    call    getfc        ;get byte
  632.     call    cknum        ;test for numeric
  633.     jnc    lnum        ;yes, continue
  634.     call    ckalp        ;test for alphabetic
  635.     jnc    lnum        ;yes, continue
  636.     jmp    main1        ;continue with main scan
  637.  
  638. lapos:    call    getfc        ;get a byte
  639.     cpi    ''''        ;see if string quote
  640.     jnz    lapos        ;no, keep looping
  641.     call    getfc        ;get next byte
  642.     cpi    ''''        ;test for doubles
  643.     jz    lapos        ;yes, start scan again
  644.     jmp    main1        ;no, continue in main scan
  645.  
  646.     if    tdl
  647. lquot:    call    getfc        ;get a byte
  648.     cpi    '"'        ;see if string quote
  649.     jnz    lquot        ;no, keep looping
  650.     call    getfc        ;get next byte
  651.     cpi    '"'        ;test for doubles
  652.     jz    lquot        ;yes, start scan again
  653.     jmp    main1        ;no, continue in main scan
  654.  
  655. ldot:    call    linit
  656.     mov    b,a        ;save character
  657.     call    getfc
  658.     cpi    '.'        ;dot dot?
  659.     jz    ldot1        ;if true, bypass local symbol
  660.     push    psw        ;save character
  661.     mov    a,b        ;restore initial character
  662.     call    gtsym        ;add to symbol
  663.     pop    psw        ;restore second char
  664.     jmp    lalph1        ;continue parsing symbol
  665.  
  666. ;   local symbol case, bypass parsing
  667.  
  668. ldot1:    call    getfc
  669.     call    ckspsy
  670.     jz    ldot1
  671.     call    cknum
  672.     jnc    ldot1
  673.     call    ckalp
  674.     jc    main1
  675.     jmp    ldot1
  676.     endif            ;tdl
  677.  
  678. llf:    lhld    lcnt        ;increment line count
  679.     inx    h
  680.     shld    lcnt
  681.     sub    a        ;reset error line flag
  682.     sta    errl
  683. llf0:    call    getfc        ;get next file char
  684.     jz    llf1        ;br if space (case normal line)
  685.  
  686.     if    mac
  687.     cpi    @ff        ;test for @ff case (.PRN from "MAC")
  688.     jz    lff        ;if true, process
  689.     cpi    @cr        ;test for @cr case (.PRN from "ASM")
  690.     jz    bypass        ;bypass formatting CRLF's
  691.     call    getfc        ;else, find out if symbol case
  692.     mvi    b,3        ;set to skip to macro cue column
  693.     jz    llf00        ;when 2nd column is blank, its an error line
  694.     call    getfc        ;if 3rd column is blank, its an error line
  695.     jz    llf00        ;no need to test for symbol table case
  696.     dcr    b        ;else, it could be symbol table case
  697.     call    skip        ;this column is always blank
  698.     jz    prsym        ;__when symbol table case
  699. llf00:    cz    skip        ;position to macro cue - 1 column
  700.     push    h        ;now we know for sure this is an error line
  701.     lhld    errorc        ;increment error count
  702.     inx    h
  703.     shld    errorc
  704.     mvi    a,true        ;flag error line
  705.     sta    errl
  706.     pop    h
  707.     call    getfc        ;resync to macro cue
  708.     jz    llf3        ;if not macro expansion line, count up
  709.     jmp    llf21        ;else, don't increment (blank) line count
  710.     endif            ;mac
  711.  
  712.     if    tdl
  713.     cpi    @cr        ;is it new line case?
  714.     jnz    llf01        ;if not
  715.     call    dcrlct        ;if so, decrement line count
  716.     call    pinit        ;init printer line buffer pointers
  717.     jmp    xref4        ;bypass new lines and proceed to header case
  718. llf01:    mvi    b,6        ;is it symbol table case?
  719.     call    skip        ;symbol value always appears at column 8
  720.     mvi    b,4        ;test for a hex character string
  721.     call    skiph0        ;returns fc/1 if non hex char detected
  722.     jnc    prsym        ;if it was really a symbol table line
  723. llf02:    dcr    b        ;else, resync to column 12
  724.     cnz    skip        ;only if not already there
  725.     lhld    errorc        ;increment error line count
  726.     inx    h
  727.     shld    errorc
  728.     mvi    a,true        ;flag error line
  729.     sta    errl
  730.     mvi    b,14        ;resync to source line
  731.     jmp    llf2        ;and proceed with parsing
  732.     endif            ;tdl
  733.  
  734. llf1:
  735.     if    mac
  736.     mvi    b,5        ;skip over address expansion
  737.     endif            ;mac
  738.  
  739.     if    tdl
  740.     mvi    b,24
  741.     endif            ;tdl
  742.  
  743. llf2:    call    skip        ;__to point to macro indicator
  744.  
  745.     if    tdl
  746.     cpi    '@'
  747.     jz    llf20
  748.     cpi    ' '
  749.     cnz    dcrlct        ;macro-expansion lines
  750. llf20:    call    getfc        ;__will be xref'ed but not counted
  751. ;    jmp    llf5
  752.     endif            ;tdl
  753.  
  754.     if    mac
  755. llf21:    cnz    dcrlct        ;anything other than space
  756.                 ;__will be treated as a macro line
  757. llf3:    mvi    b,11        ;skip over object code expansion
  758. llf4:    call    skip        ;(first 16 chars of a line in .PRN file)
  759.     endif            ;mac
  760.  
  761. llf5:    cpi    '*'        ;test for special '*' comment line case
  762.     jnz    main1        ;if not true, parse remainder of file
  763. ;    jmp    lsemi        ;else, consider line as a comment
  764.  
  765. lsemi:    call    bypln        ;bypass parsing of the line (till @cr)
  766.     jmp    main1        ;parse remainder of file
  767.  
  768. bypass:
  769.     call    dcrlct        ;decrement line count
  770.     jmp    lsemi        ;treat rest of line as a comment line
  771.  
  772. lff:    if    mac
  773.     sub    a        ;reset page line count
  774.     sta    lines
  775.     call    getfc        ;get next file char & test for space
  776.     jnz    lff2        ;if not normal case, test for symbol or header
  777.     call    getfc        ;test for weird page case
  778.     mvi    b,4        ;prepare to sync to macro cue
  779.     jnz    llf2        ;if normal line
  780.     mvi    b,14        ;# of chars to skip over object expansion
  781. lff0:    call    getfc        ;skip over object field
  782.     jz    lff1        ;if not object, test for page case
  783.     dcr    b        ;prepare to enter skip loop
  784.     jnz    llf4        ;it is not page case, enter normal parsing loop
  785.     jmp    former        ;cannot be any other case, file is corrupted
  786. lff1:    dcr    b        ;-- count
  787.     jnz    lff0        ;see if at end of object expansion, loop if not
  788.     call    getfc        ;test for page case
  789.     cpi    @cr
  790.     jnz    llf5        ;if really not page, then test for comment
  791.     call    getfc        ;if page case, next char
  792.     cpi    @lf        ;__must be line feed
  793.     jnz    former        ;else we've got problems
  794.     call    prline        ;just print out (hopefully) blank line
  795.     call    crlft        ;this is why page case is WEIRD!
  796.     jmp    main        ;re-enter main parsing loop
  797. lff2:    call    skiphx        ;test for symbol line case
  798.     jc    lff3        ;if not a symbol table line
  799.     call    getfc        ;now, test for a space
  800.     jz    prsym        ;if really a symbol table line
  801.     call    getfc        ;test for a error source line case
  802.     jz    llf3        ;if true
  803.     cpi    'M'        ;try for a header line case
  804.     jnz    bypass        ;if none of above, treat as for a macro case
  805. lff3:    call    bypln        ;just save rest of line in line buffer
  806.     call    prline        ;and print out w/o numbers
  807.     call    crlft        ;__with the attendant prettyprinting
  808.     call    getbt        ;bypass following @lf and discard
  809.     cpi    @lf        ;just make sure were discarding the right char
  810.     jnz    former        ;if file format error
  811.     call    getfc        ;next char in file should be @lf
  812.     cpi    @lf        ;check that character was indeed a @lf
  813.     jz    llf0        ;if true, proceed parsing file as for @lf case
  814. ;    jmp    former        ;else, we've got a problem
  815.     endif            ;mac
  816.  
  817. former:    call    fcdisp        ;print warning and terminate program
  818.     db    @bel,'+++ .PRN file format corrupted +++',@cr,@lf,@nul
  819.     jmp    exit        ;too bad!;(sorry... can't handle it yet)
  820.  
  821. prsym:    sub    a        ;deactivate summary option
  822.     sta    summary
  823.     call    dcrlct        ;decrement line count
  824. prsym1:    call    bprlin        ;bypass parsing of the line & unadorned print
  825.     jmp    lcr1        ;update page line count & exit
  826.  
  827. lcr:    call    prlinu        ;print source and line id
  828. lcr1:    call    ckpass        ;don't increment page line count
  829.     jz    main        ;if pass 2
  830.     lda    lines        ;increment page line count
  831.     inr    a
  832.     sta    lines
  833.     cpi    pglen        ;test for forms length
  834.     jnz    main        ;re-enter main character parsing loop
  835.     call    formf        ;time to form feed
  836.     call    getbt        ;bypass saving following @lf
  837.     cpi    @lf        ;only if char is @lf
  838.     jz    llf        ;if @lf
  839.     call    savbt        ;else save
  840.     jmp    main1        ;and continue parsing
  841.  
  842. linit:    lxi    h,sbuf        ;erase temporary symbol buffer
  843.     mvi    c,symsiz
  844.     mvi    a,' '
  845. linit1:    mov    m,a
  846.     inx    h
  847.     dcr    c
  848.     jnz    linit1
  849.     lxi    h,sbuf        ;reset symbol ^
  850.     shld    sympt
  851.     sub    a        ;reset count
  852.     sta    symct
  853.     lda    char        ;restore previously read char
  854.     ret
  855.  
  856. dcrlct:    lhld    lcnt
  857.     dcx    h
  858.     shld    lcnt
  859.     ret
  860.  
  861. ckpass:    lda    pass        ;is it pass 1 or 2?
  862.     ora    a        ;pass 1 = nz, pass 2 = 0
  863.     rnz
  864.     sta    summary        ;disable summary flag
  865.     ret
  866.  
  867. ckcon:    lda    crt        ;console trace option active?
  868.     ora    a        ;true if nz
  869.     ret
  870.  
  871. ckdsk:    lda    diskl        ;disk output option active?
  872.     ora    a        ;true if nz
  873.     ret
  874.  
  875. ckerr:    lda    error        ;error only option active?
  876.     ora    a        ;true if nz
  877.     ret
  878.  
  879. ckban:    lda    nobanr        ;no banner option selected?
  880.     ora    a        ;true if nz
  881.     ret
  882.  
  883. ckquiet:lda    quiet        ;quiet operation selected?
  884.     ora    a        ;true if nz
  885.     ret
  886.  
  887. cksumo:    lda    summary        ;summary option active?
  888.     ora    a        ;true if nz
  889.     ret
  890.  
  891. ckentab:lda    entab        ;enter tabs option active?
  892.     ora    a
  893.     ret
  894.  
  895.     if    tdl
  896. skipnl:    call    getlf
  897.     jnz    former
  898.     call    getcr
  899.     rc
  900.     jz    skipnl
  901.     rrc
  902.     cpi    @nul
  903.     jnz    skipn1
  904.     endif            ;tdl
  905.  
  906. skipn0:    lhld    way
  907.     pchl
  908.  
  909.     if    tdl
  910. skipn1:    push    psw
  911.     call    crlf2
  912.     pop    psw
  913.     call    savbt
  914.     jmp    prsym1
  915.     
  916. getlf:    call    getbt
  917.     cpi    @lf
  918.     ret
  919.  
  920. getcr:    call    getbt
  921.     cpi    @cr
  922.     rz
  923.     rlc
  924.     ret
  925.  
  926. header:    sub    a
  927.     sta    char        ;(clear for bypln)
  928.  
  929. ;   print out first 4 lines of header as is
  930.  
  931.     mvi    b,4
  932. heade0:    push    b
  933.     call    bprlin        ;print source line w/o formatting
  934.     call    getfc        ;get char following @CR (for bypln)
  935.     pop    b
  936.     dcr    b        ;adj. count
  937.     jnz    heade0        ;loop till done
  938.  
  939. ;   test to see if symbol table page case
  940.  
  941.     mvi    b,5
  942.     lxi    h,pbuf+1
  943.     mvi    a,'+'
  944. heade1:    cmp    m
  945.     jnz    heade2
  946.     inx    h
  947.     dcr    b
  948.     jnz    heade1
  949.     call    bprlin        ;print source line w/o formatting
  950.     jmp    heade3
  951.  
  952. ;   normal listing page case
  953.  
  954. heade2:    call    ckpass        ;don't pretty-print
  955.     jz    heade21        ;__if pass 2
  956.     call    crlf
  957.     call    ldisp        ;replace blank line with pretty-print
  958.     db    ' Location  Object-code   Line#  Source line',@NUL
  959. heade21:call    bypln
  960.  
  961. ;   proper subroutine ending
  962.  
  963. heade3:    call    getfc
  964.     call    bprlin        ;print source line w/o formatting
  965.     jmp    getfc        ;indirect return
  966.     endif            ;tdl
  967.  
  968. ;/******************************/
  969. ;
  970. ;   initialization
  971. ;
  972. ;/******************************/
  973.  
  974. setup:    sub    a        ;disable all options
  975.     sta    crt
  976.     sta    diskl
  977.     sta    error
  978.     sta    nobanr
  979.     sta    quiet
  980.     sta    summary
  981.     sta    entab
  982.     sta    warning
  983.  
  984. ;   parse command line
  985.  
  986.     lxi    h,dma        ;^ to command line tail
  987.     shld    bufadd
  988.     ora    m        ;anything entered?
  989.     jnz    setu0        ;if yes, test file type
  990.  
  991. ;   Give a little bit of help
  992.  
  993. help:    call    cdisp        ;else print help message
  994.     db    @cr,@lf,'Usage:'
  995.     db    @cr,@lf,@lf,'   [d:]xref [d:]fn.ft [d:][/ooo...]'
  996.     db    @cr,@lf,@lf,'where ''[]'' denotes optional entry'
  997.     db    @cr,@lf,'and ''o'' stands for a valid option identifier.'
  998.     db    @cr,@lf,@lf,'Selectable options are:'
  999.     db    @cr,@lf,'   c  -  CON: trace'
  1000.     db    @cr,@lf,'   d  -  disk file listing'
  1001.     db    @cr,@lf,'      forces fn.LST as output file'
  1002.     db    @cr,@lf,'      with option t in effect'
  1003.     db    @cr,@lf,'   e  -  list error lines only'
  1004.     db    @cr,@lf,'   n  -  no banner expansion'
  1005.     db    @cr,@lf,'   q  -  quiet mode'
  1006.     db    @cr,@lf,'   s  -  summary report only'
  1007.     db    @cr,@lf,'   t  -  compress blanks to tabs'
  1008.     db    @cr,@lf,@lf,'Note: if no file type is specified,'
  1009.     db    @cr,@lf,'      the default .PRN will be assumed.'
  1010.     db    @cr,@lf,'      A null file type is entered as a ''.'' (dot).'
  1011.     db    @cr,@lf,@nul
  1012.     jmp    exit1        ;__and return to CP/M
  1013.  
  1014. ;   file name was entered
  1015.  
  1016. setu0:    mvi    a,'.'        ;look to see if file type defined
  1017.     call    findb
  1018.     jnc    setu00        ;if yes, take file type as is
  1019.     mvi    a,'P'        ;else, assume .PRN file
  1020.     sta    fcb+9
  1021.     lxi    h,'RN'
  1022.     shld    fcb+10
  1023.  
  1024. ;   ckeck out options wanted
  1025.  
  1026. setu00:    lxi    h,dma
  1027.     mvi    a,'/'        ;look for option delimiter
  1028.     call    findb
  1029.     jc    setu1        ;if none found
  1030.     dcr    b        ;any char following?
  1031.     jnz    setu02        ;if yes
  1032. setu01:    call    fcdisp        ;undecipherable option was entered
  1033.     db    @bel,'+++ Option error +++',@nul
  1034.     jmp    help
  1035. setu02:    inx    h        ;get next char
  1036.     mov    a,m
  1037.     cpi    'D'        ;disk listing option?
  1038.     jnz    setu03
  1039.     mvi    a,true
  1040.     sta    diskl
  1041.     sta    entab
  1042.     jmp    setu09
  1043. setu03:    cpi    'E'        ;error only option?
  1044.     jnz    setu04
  1045.     mvi    a,true
  1046.     sta    error
  1047.     jmp    setu09
  1048. setu04:    cpi    'N'        ;no banner option?
  1049.     jnz    setu05
  1050.     mvi    a,true
  1051.     sta    nobanr
  1052.     jmp    setu09
  1053. setu05:    cpi    'S'        ;summary only option?
  1054.     jnz    setu06
  1055.     mvi    a,true
  1056.     sta    summary
  1057.     jmp    setu09
  1058. setu06:    cpi    'C'        ;CON: trace option?
  1059.     jnz    setu07
  1060.     mvi    a,true
  1061.     sta    crt
  1062.     sta    quiet
  1063.     jmp    setu09
  1064. setu07:    cpi    'Q'        ;quiet option?
  1065.     jnz    setu08
  1066.     mvi    a,true
  1067.     sta    quiet
  1068.     jmp    setu09
  1069. setu08:    cpi    'T'        ;compress tabs option?
  1070.     jnz    setu01        ;can't be anything else
  1071.     mvi    a,true
  1072.     sta    entab
  1073. ;    jmp    setu09
  1074. setu09:    dcr    b        ;more chars available?
  1075.     jnz    setu02        ;if yes
  1076.  
  1077. setu1:    lxi    d,fcb        ;point to fcb
  1078.     lxi    h,ifcb        ;save a copy of initial fcb
  1079.     mvi    b,fcbl        ;__for later use by pass 2
  1080.     call    move
  1081.  
  1082. ;   create disk file output fcb
  1083.  
  1084.     call    ckdsk        ;disk output option active?
  1085.     jz    setu12        ;if not
  1086. setu11:    lda    fcb2        ;get drive number
  1087.     sta    dfcb
  1088.     lxi    d,fcb+1        ;copy source filename
  1089.     lxi    h,dfcb+1    ;__to destination filename
  1090.     mvi    b,8
  1091.     call    move
  1092.     mvi    m,'L'        ;force ft to 'LST'
  1093.     inx    h
  1094.     mvi    m,'S'
  1095.     inx    h
  1096.     mvi    m,'T'
  1097.     sub    a
  1098.     sta    dfcb+32        ;clear current record
  1099.  
  1100. ;   open source file
  1101.  
  1102. setu12:    lxi    d,fcb
  1103.     call    fopen        ;open fcb
  1104.     jnc    setu13        ;psw/c0, open ok
  1105.     call    fcdisp
  1106.     db    '+++ File not found +++',@cr,@lf,@nul
  1107.     jmp    exit        ;exit back to ccp
  1108.  
  1109. ;   if disk output wanted, open destination file
  1110.  
  1111. setu13:    call    ckdsk        ;disk output option active?
  1112.     jz    setu2        ;if not
  1113.     lxi    d,dfcb        ;^ destination fcb
  1114.     mvi    c,findf        ;look for destination filename
  1115.     call    bdos
  1116.     inr    a        ;does file already exists?
  1117.     jz    setu14        ;if not, bypass delete
  1118.     lxi    d,dfcb
  1119.     mvi    c,deletf    ;else, delete the file
  1120.     call    bdos
  1121. setu14:    lxi    d,dfcb
  1122.     mvi    c,makef        ;now, create the destination file
  1123.     call    bdos
  1124.     inr    a
  1125.     jnz    setu2        ;opening sucessfull
  1126.     call    fcdisp
  1127.     db    'no directory space ',@nul
  1128.     jmp    abort
  1129.  
  1130. ;   init variables for 1st pass
  1131.  
  1132. setu2:    sub    a        ;enable pass 1 flag
  1133.     cma
  1134.     sta    pass
  1135.     lxi    h,done        ;where to go when eof hit
  1136.     shld    way
  1137.     call    initp        ;init disk & printer variables 
  1138.     lxi    h,symt        ;set symbol table pointers
  1139.     mvi    m,-1        ;__and xref variables
  1140.     shld    sym        
  1141.     shld    symbt
  1142.     shld    symtp
  1143.  
  1144. ;   check if BDOS v2.2 present
  1145.  
  1146.     if    cpm22
  1147.     mvi    c,cpmver
  1148.     call    bdos
  1149.     cpi    22h
  1150.     jz    setu3        ;if okay
  1151.     call    cdisp
  1152.     db    'Warning! this is not CP/M 2.2',@cr,@lf,@nul
  1153.     cma
  1154.     sta    warning
  1155.     jmp    setu4
  1156. setu3:    lhld    fbase        ;get BDOS entry vector + 6
  1157.     lxi    d,30Eh-6    ;offset to last char read flag
  1158.     dad    d
  1159.     shld    lastci        ;save vector
  1160.     endif            ;cpm22
  1161.  
  1162. ;   calculate top of free RAM
  1163.  
  1164. setu4:    lhld    fbase        ;get highest available memory + 7
  1165.     lxi    d,-(800h+7)    ;substract CCP + 7 size
  1166.     dad    d        ;to get start of CCP ^ - 1 (last free RAM)
  1167.     shld    ref        ;set reference table pointers
  1168.     shld    refbt
  1169.     shld    reftp
  1170.     ret
  1171.  
  1172. ;   common initialization routines
  1173.  
  1174. initp:    call    pinit        ;set line buffer ^
  1175.     lxi    h,0
  1176.     shld    errorc        ;reset error count
  1177.  
  1178.     if    mac
  1179.     inx    h
  1180.     endif            ;mac
  1181.  
  1182.     shld    lcnt        ;reset line count
  1183.     lxi    h,tbuf+(tbsze*128) ;reset disk buffer pointers
  1184.     shld    tbdma
  1185.     shld    inptr
  1186.     lxi    h,tbuf        ;^ to start of disk buffer
  1187.     lxi    b,symt-tbuf    ;calculate buffer size
  1188. initp1:    mvi    m,eof        ;fill buffer area with eof's
  1189.     inx    h
  1190.     dcx    b
  1191.     mov    a,c
  1192.     ora    b
  1193.     jnz    initp1        ;loop till done
  1194. ;    sub    a
  1195.     sta    tbflg
  1196.     ret
  1197.  
  1198. ;/******************************/
  1199. ;
  1200. ;   skip n characters
  1201. ;   in line buffer
  1202. ;
  1203. ;/******************************/
  1204.  
  1205. skip:    call    getfc        ;get a byte
  1206.     dcr    b        ;-- count
  1207.     jnz    skip        ;loop till done
  1208.     cpi    ' '        ;set psw/z1 if space
  1209.     ret
  1210.  
  1211. ;/******************************/
  1212. ;
  1213. ;   skip to end of line
  1214. ;
  1215. ;/******************************/
  1216.  
  1217. bypln:    lda    char        ;get current character
  1218.     cpi    @cr        ;test for end of line delimiter
  1219.     rz            ;return when one found
  1220.     call    getfc        ;else, get next file char
  1221.     jmp    bypln        ;and test again
  1222.  
  1223. ;/******************************/
  1224. ;
  1225. ;   test for hex char in
  1226. ;   address expansion field
  1227. ;
  1228. ;/******************************/
  1229.  
  1230. skiphx:    mvi    b,3        ;3 following char should be hex
  1231. skiph0:    call    getfc        ;get char
  1232.     call    ckhex        ;test for hex
  1233.     rc            ;exit with psw/c1 if not hex
  1234.     dcr    b        ;-- count
  1235.     jnz    skiph0        ;loop till done
  1236.     ret
  1237.  
  1238. ;/******************************/
  1239. ;
  1240. ;   check for reserved word
  1241. ;
  1242. ;/******************************/
  1243.  
  1244. cres:    lxi    h,rtab        ;point to reserved word table
  1245.     shld    temp        ;save in temp word
  1246. cres1:    lhld    temp        ;get table pointer
  1247.     lxi    d,sbuf        ;point to symbol
  1248.     mvi    b,rsiz        ;symbol size
  1249. cres2:    ldax    d        ;get symbol byte
  1250.     cmp    m        ;compare against table entry
  1251.     rc            ;less, not in table
  1252.     jnz    cres3        ;greater, get next table entry
  1253.     inx    d        ;bump pointers
  1254.     inx    h
  1255.     dcr    b        ;decrement byte count
  1256.     jnz    cres2        ;keep testing
  1257.     jmp    cres4        ;found
  1258. cres3:    lhld    temp        ;get table pointer
  1259.     lxi    d,rsiz        ;size of entry
  1260.     dad    d        ;bump pointer
  1261.     shld    temp        ;store new pointer
  1262.     call    endoft        ;test for end of table
  1263.     jnz    cres1        ;no, loop
  1264.     stc            ;set carry (not in table)
  1265.     ret
  1266. cres4:    ora    a        ;reset carry
  1267.     ret
  1268.  
  1269. ;/******************************/
  1270. ;
  1271. ;   find symbol in table
  1272. ;
  1273. ;/******************************/
  1274.  
  1275. find:    lhld    symbt        ;get begin of sym table
  1276.     shld    sym        ;set temp pointer
  1277. find1:    lhld    sym        ;get temp pointer
  1278.     lxi    d,sbuf        ;point to current symbol
  1279.     mvi    b,symsiz    ;symbol size
  1280. find2:    ldax    d        ;get byte from sbuf
  1281.     cmp    m        ;compare to sym table byte
  1282.     rc            ;greater, not in table
  1283.     jnz    find3        ;less, get next table entry
  1284.     inx    d        ;bump pointer
  1285.     inx    h        ;bump pointer
  1286.     dcr    b        ;decrement byte count
  1287.     jnz    find2        ;loop
  1288.     ret            ;true zero, found
  1289. find3:    lhld    sym        ;get current pointer
  1290.     lxi    d,ssiz        ;symbol table entry size
  1291.     dad    d        ;bump pointer
  1292.     xchg            ;into de
  1293.     lhld    symtp        ;get top of symbol table
  1294.     call    cphl        ;test for end of table
  1295.     jz    find4        ;yes, done
  1296.     jnc    find31        ;psw/c0, everything ok, br if so
  1297. ferr:    call    fcdisp        ;table overflow, error
  1298.     db    '+++ Symbol table overflow +++',@cr,@lf,@nul
  1299.     jmp    exit        ;return to ccp
  1300. find31:    xchg            ;current pointer into hl
  1301.     shld    sym        ;set current pointer
  1302.     jmp    find1        ;loop
  1303. find4:    stc            ;set carry for not found
  1304.     lhld    symtp        ;get current top
  1305.     shld    sym        ;set current pointer
  1306.     ret
  1307.  
  1308. ;/******************************/
  1309. ;
  1310. ;   add reference to ref table
  1311. ;
  1312. ;/******************************/
  1313.  
  1314. addrf:    lhld    sym        ;get symbol pointer
  1315.     lxi    d,symsiz+1    ;offset past symbol&flags
  1316.     dad    d
  1317.     mov    e,m
  1318.     inx    h
  1319.     mov    d,m        ;get reference pointer
  1320.     lxi    h,0
  1321.     call    cphl        ;test for zero ref ptr
  1322.     jz    bldrf        ;yes, build reference entry
  1323. link:    xchg            ;ref ptr in hl
  1324.     mov    e,m        ;get ref link
  1325.     inx    h
  1326.     mov    d,m        ;into de
  1327.     dcx    h        ;reposition hl
  1328.     push    h        ;save ref ptr
  1329.     lxi    h,0
  1330.     call    cphl        ;if link is zero
  1331.     pop    h
  1332.     jnz    link        ;non zero, get next link
  1333.     shld    ref        ;save ref pointer
  1334.     inx    h
  1335.     inx    h        ;skip to first ref number
  1336.     mvi    b,(refsz-2)/2    ;number of ref numbers/entry
  1337. link3:    mov    e,m        ;get ref number
  1338.     inx    h
  1339.     mov    d,m
  1340.     dcx    h        ;reposition
  1341.     push    h        ;save ref num addr
  1342.     lxi    h,0
  1343.     call    cphl        ;see if ref num is zero
  1344.     pop    h
  1345.     jz    enref        ;yes, enter reference
  1346.     inx    h
  1347.     inx    h        ;skip to next ref num
  1348.     dcr    b        ;decrement count
  1349.     jnz    link3        ;try again at next slot
  1350.     call    adblk        ;add new ref block
  1351.     lhld    ref        ;get ref pointer
  1352.     inx    h
  1353.     inx    h        ;skip to first ref slot
  1354. enref:    push    h        ;save ref slot addr
  1355.     lhld    lcnt        ;get line number
  1356.     xchg            ;into de
  1357.     pop    h        ;get ref slot addr
  1358.     mov    m,e
  1359.     inx    h
  1360.     mov    m,d        ;store line ref
  1361.     ret            ;done
  1362.  
  1363. ;/******************************/
  1364. ;
  1365. ;   build ref table block
  1366. ;
  1367. ;/******************************/
  1368.  
  1369. bldrf:    lhld    sym        ;get symbol pointer
  1370.     lxi    d,symsiz+1    ;offset to ref pointer
  1371.     dad    d
  1372.     shld    ref        ;set temp ref pointer to here
  1373.     call    adblk        ;add block
  1374.     lhld    ref        ;get real ref pointer
  1375.     inx    h
  1376.     inx    h        ;position to first ref slot
  1377.     jmp    enref        ;add reference
  1378. adblk:    lhld    refbt        ;get ref bottom
  1379.     lxi    d,refsz        ;subtract ref size
  1380.     mov    a,l
  1381.     sub    e
  1382.     mov    l,a
  1383.     mov    a,h
  1384.     sbb    d
  1385.     mov    h,a
  1386.     shld    temp        ;save new ref bottom
  1387.     xchg            ;into de also
  1388.     lhld    symtp        ;get symbol top
  1389.     call    cphl        ;check for bump
  1390.     jz    ferr        ;yes, no room
  1391.     jnc    ferr        ;no room
  1392.     lhld    temp        ;get ref bottom
  1393.     xchg            ;into de
  1394.     lhld    ref        ;get ref pointer
  1395.     mov    m,e        ;set link
  1396.     inx    h
  1397.     mov    m,d        ;to new ref block
  1398.     lhld    temp        ;get new ref block addr
  1399.     shld    ref        ;store in ref
  1400.     mvi    b,refsz        ;size of ref block
  1401.     sub    a
  1402. adb2:    mov    m,a        ;zero the ref block
  1403.     inx    h
  1404.     dcr    b
  1405.     jnz    adb2
  1406.     lhld    temp        ;get new ref bottom
  1407.     shld    refbt        ;set refbt
  1408.     ret
  1409.  
  1410. ;/******************************/
  1411. ;
  1412. ;   enter symbol in sym table
  1413. ;
  1414. ;/******************************/
  1415.  
  1416. ensym:    lhld    sym        ;get symbol pointer
  1417.     xchg            ;into de
  1418.     lhld    symtp        ;get symbol table top
  1419.     call    cphl        ;check for end of table
  1420.     jz    nwsym        ;yes, add symbol at end
  1421.     lxi    d,ssiz        ;symbol table entry size
  1422.     dad    d        ;calculate new end of table
  1423.     xchg            ;into de
  1424.     lhld    refbt        ;reference table bottom
  1425.     call    cphl        ;test for table overflow
  1426.     jz    ferr        ;full, error
  1427.     jc    ferr        ;yes, error
  1428.     lhld    symtp        ;get table top
  1429.     lxi    d,ssiz-1    ;bump to end of entry
  1430.     dad    d
  1431.     shld    to        ;store in to address
  1432.     lxi    d,ssiz
  1433.     mov    a,l
  1434.     sub    e
  1435.     mov    l,a
  1436.     mov    a,h
  1437.     sbb    d
  1438.     mov    h,a        ;subtract size of one entry
  1439.     shld    from        ;store as from address
  1440.     lhld    sym        ;get current pointer
  1441.     shld    limit        ;store as limit address
  1442.     call    mvup        ;move table up in memory
  1443. nwsym:    lhld    sym        ;get current pointer
  1444.     lxi    d,sbuf        ;point to symbol
  1445.     mvi    b,symsiz    ;size of symbol
  1446.     call    move        ;copy symbol to table
  1447.     sub    a
  1448.     mov    m,a
  1449.     inx    h
  1450.     mov    m,a
  1451.     inx    h
  1452.     mov    m,a        ;set pointers to 0000
  1453.     lhld    symtp        ;get symbol table top
  1454.     lxi    d,ssiz        ;get symbol entry size
  1455.     dad    d        ;bump
  1456.     shld    symtp        ;store ew top
  1457.     ret
  1458.  
  1459. ;/******************************/
  1460. ;
  1461. ;   move symbol table up
  1462. ;
  1463. ;/******************************/
  1464.  
  1465. mvup:    lhld    to        ;get to pointer
  1466.     mov    b,h
  1467.     mov    c,l        ;into bc
  1468.     lhld    from        ;get from pointer
  1469.     xchg            ;into de
  1470.     lhld    limit        ;get limit address
  1471. mvup2:    ldax    d        ;get from byte
  1472.     stax    b        ;store at to address
  1473.     call    cphl        ;compare from to limit
  1474.     rz            ;exit if done
  1475.     dcx    b        ;decrement to
  1476.     dcx    d        ;decrment from
  1477.     jmp    mvup2        ;loop
  1478.  
  1479. ;/******************************/
  1480. ;
  1481. ;   general purpose move routine
  1482. ;
  1483. ;/******************************/
  1484.  
  1485. move:    ldax    d        ;get byte
  1486.     mov    m,a        ;store byte
  1487.     inx    d
  1488.     inx    h        ;bump pointers
  1489.     dcr    b        ;decrement count
  1490.     jnz    move        ;loop
  1491.     ret
  1492.  
  1493. ;/******************************/
  1494. ;
  1495. ;   general purpose find routine
  1496. ;
  1497. ; entry:
  1498. ;    hl    ^ count,string
  1499. ;    a    byte searched
  1500. ; exit:
  1501. ;    hl    ^ found byte
  1502. ;    fc    if not found
  1503. ; uses:
  1504. ;    hl,b,a,psw
  1505. ;
  1506. ;/******************************/
  1507.  
  1508. findb:    mov    b,m
  1509. findb0:    inx    h
  1510.     cmp    m
  1511.     rz
  1512.     dcr    b
  1513.     jnz    findb0
  1514.     stc
  1515.     ret
  1516.  
  1517. ;/******************************/
  1518. ;
  1519. ;   binary to decimal conversion
  1520. ;
  1521. ;/******************************/
  1522.  
  1523. decotj:    call    decot        ;convert value in hl to decimal
  1524.     lxi    h,dec        ;set to blank out leading zeroes
  1525.     mvi    a,'0'
  1526. decot1:    cmp    m        ;by converting all zero characters to spaces
  1527.     rnz            ;exit when first non-zero char hit
  1528.     mvi    m,' '        ;else proceed with filter loop
  1529.     inx    h
  1530.     jmp    decot1
  1531.  
  1532. decot:    lxi    d,dec        ;there are more elegant ways to do this
  1533.     xchg            ;__but this one is simple enough
  1534.     lxi    b,10000        ;__and creates a string as result
  1535.     call    dig        ;__which then can be justified.
  1536.     lxi    b,1000
  1537.     call    dig
  1538.     lxi    b,100
  1539.     call    dig
  1540.     lxi    b,10
  1541.     call    dig
  1542.     lxi    b,1
  1543.     call    dig
  1544.     ret
  1545.  
  1546. dig:    mvi    m,'0'
  1547. di0:    mov    a,e
  1548.     sub    c
  1549.     mov    e,a
  1550.     mov    a,d
  1551.     sbb    b
  1552.     mov    d,a
  1553.     jm    di2
  1554.     inr    m
  1555.     jmp    di0
  1556. di2:    mov    a,e
  1557.     add    c
  1558.     mov    e,a
  1559.     mov    a,d
  1560.     adc    b
  1561.     mov    d,a
  1562.     inx    h
  1563.     ret
  1564.  
  1565. ;/******************************/
  1566. ;
  1567. ;   check for special
  1568. ;   symbol character
  1569. ;
  1570. ;/******************************/
  1571.  
  1572. ckspsy:
  1573.     if    mac
  1574.     cpi    '@'
  1575.     rz
  1576.     cpi    '?'
  1577.     ret
  1578.     endif            ;mac
  1579.  
  1580.     if    tdl
  1581.     cpi    '$'
  1582.     rz
  1583.     cpi    '%'
  1584.     rz
  1585.     cpi    '.'
  1586.     ret
  1587.     endif            ;tdl
  1588.  
  1589. ;/******************************/
  1590. ;
  1591. ;   test for alphabetic char.
  1592. ;
  1593. ;/******************************/
  1594.  
  1595. ckalp:    cpi    'A'        ;test for ascii characters
  1596.     rc            ;between 'A' and 'Z'
  1597.     cpi    'Z'+1        ;returns psw/c0 if within range
  1598.     cmc
  1599.     rnc
  1600.     cpi    'a'        ;also test lowercase alpha characters
  1601.     rc
  1602.     cpi    'z'+1
  1603.     cmc
  1604.     ret
  1605.  
  1606. ;/******************************/
  1607. ;
  1608. ;   test for numeric char
  1609. ;
  1610. ;/******************************/
  1611.  
  1612. cknum:    cpi    '0'        ;test for ascii characters
  1613.     rc            ;between '0' and '9'
  1614.     cpi    '9'+1        ;returns psw/c0 if within range
  1615.     cmc
  1616.     ret
  1617.  
  1618. ;/******************************/
  1619. ;
  1620. ;   test for hexadecimal char
  1621. ;
  1622. ;/******************************/
  1623.  
  1624. ckhex:    cpi    '0'        ;smaller than '0' ?
  1625.     rc            ;if yes
  1626.     cpi    'F'+1        ;greater than 'F' ?
  1627.     cmc
  1628.     rc            ;if yes
  1629.     cpi    '9'+1        ;if smaller than ':' then ok
  1630.     cmc
  1631.     rnc            ;if true
  1632.     cpi    'A'        ;if not smaller than 'A' then ok
  1633.     ret
  1634.  
  1635. ;/******************************/
  1636. ;
  1637. ;   test for printable char
  1638. ;
  1639. ;/******************************/
  1640.  
  1641. ckpra:    cpi    ' '        ;test for ascii characters
  1642.     rc            ;between ' ' and 'z'
  1643.     cpi    'z'+1        ;returns psw/c0 if within range
  1644.     cmc
  1645.     ret
  1646.  
  1647. ;/******************************/
  1648. ;
  1649. ;   test end of table
  1650. ;
  1651. ;/******************************/
  1652.  
  1653. endoft:    mov    a,m
  1654.     cpi    -1
  1655.     ret
  1656.  
  1657. ;/******************************/
  1658. ;
  1659. ;   map char to upper case
  1660. ;
  1661. ;/******************************/
  1662.  
  1663. mupc:    cpi    'a'        ;is it smaller than 'a'?
  1664.     cmc            ;just to be neat
  1665.     rnc            ;if true, can't map
  1666.     cpi    'z'+1        ;is it greater than 'z'?
  1667.     rnc            ;if true, can't map
  1668.     sui    20h        ;'a' <= char <= 'z' so convert
  1669.     ret
  1670.  
  1671. ;/******************************/
  1672. ;
  1673. ;   check for special characters
  1674. ;
  1675. ;/******************************/
  1676.  
  1677. ckspc:    lxi    h,ctab        ;point to special characters table
  1678. ;    jmp    look
  1679.  
  1680. look:    lxi    d,3        ;table entry size
  1681.     mov    b,a        ;argument byte in b
  1682. look2:    call    endoft        ;test for end of table
  1683.     jz    lookn        ;yes, not found
  1684.     cmp    b        ;compare
  1685.     jz    looky        ;found
  1686.     dad    d        ;bump pointer
  1687.     jmp    look2        ;loop
  1688. lookn:    stc            ;carry = not found
  1689.     ret
  1690.  
  1691. looky:    inx    h        ;skip to table byte
  1692.     mov    e,m
  1693.     inx    h
  1694.     mov    d,m        ;table entry in de
  1695.     xchg            ;into hl
  1696.     ret
  1697.  
  1698. ;/******************************/
  1699. ;
  1700. ;   save byte in line buffer
  1701. ;
  1702. ;/******************************/
  1703.  
  1704. savbt:    sta    char        ;save char in char
  1705.     lhld    lpnt        ;get line pointer
  1706.     mov    m,a        ;save byte
  1707.     inx    h        ;bump pointer
  1708.     shld    lpnt        ;save pointer
  1709.     ret
  1710.  
  1711. ;/******************************/
  1712. ;
  1713. ;   print source line with number
  1714. ;
  1715. ;/******************************/
  1716.  
  1717. prlinu:    call    curpas        ;check which pass is active
  1718.  
  1719. ;   print object expansion of .PRN file
  1720.  
  1721. pl0:
  1722.     if    mac
  1723.     mvi    b,16
  1724.     endif
  1725.  
  1726.     if    tdl
  1727.     mvi    b,24        ;set loop count
  1728.     endif
  1729.  
  1730. pl1:    call    getlc        ;get a line buffer character
  1731.     jc    pl4        ;when psw/c1, @cr (end of line) was reached
  1732.     call    ckpra        ;test for printable character
  1733.     cc    lpdvd        ;could be a formatting char, print out anyway
  1734.     jc    pl1        ;__but skip count
  1735.     call    lpdvd        ;else, print out character to line printer
  1736.     dcr    b        ;-- count
  1737.     jnz    pl1        ;loop till done
  1738.  
  1739. ;   print out line number
  1740.  
  1741.     push    h        ;save line buffer ^
  1742.  
  1743.     if    mac
  1744.     lda    errl        ;test for error line
  1745.     ora    a        ;none if false (0)
  1746.     jz    pl11        ;if no error
  1747.     mvi    e,' '        ;prettyprint
  1748.     call    lpdvd        ;__to enhance error line number
  1749.     call    lpdvd
  1750.     mvi    e,'*'
  1751.     mvi    b,3
  1752. pl10:    call    lpdvd
  1753.     dcr    b
  1754.     jnz    pl10
  1755. pl11:    call    lptab        ;print out a tab (to align on a tab stop)
  1756.     endif            ;mac
  1757.  
  1758.     lhld    lastp        ;get previous line count
  1759.     xchg            ;compare last line # to current one
  1760.     lhld    lcnt        ;get current line count
  1761.     call    cphl        ;do the compare
  1762.     shld    lastp        ;update last line printed variable
  1763.     jnz    pl2        ;if line is different
  1764.     lxi    h,0        ;blank out same line #
  1765. pl2:    call    prdec        ;print out decimal string
  1766.  
  1767.     if    mac
  1768.     call    lptab        ;print out a tab (to align on a tab stop)
  1769.     endif            ;mac
  1770.  
  1771.     if    tdl
  1772.     mvi    e,' '
  1773.     mvi    b,2
  1774. pl21:    call    lpdvd
  1775.     dcr    b
  1776.     jnz    pl21
  1777.     endif            ;tdl
  1778.  
  1779.     pop    h        ;restore line buffer ^
  1780.  
  1781. ;   print out remainder of source line
  1782.  
  1783. pl3:    call    getlc        ;get a char. from line buffer
  1784.     jc    pl4        ;when psw/c1, end of line so br out
  1785.     call    lpdvd        ;print out character
  1786.     jmp    pl3        ;loop for more
  1787.  
  1788. ;   and exit back
  1789.  
  1790. pl4:    call    lpdvd        ;print out @cr (to flush line printer)
  1791.     call    pinit        ;reset line buffer^
  1792.     ret
  1793.  
  1794. ;/******************************/
  1795. ;
  1796. ;   print out line buffer
  1797. ;
  1798. ;/******************************/
  1799.  
  1800. bprlin:    call    bypln        ;bypass parsing of the line
  1801. prline:    call    curpas        ;check which pass is active
  1802.     jmp    pl3        ;print out entire line
  1803.  
  1804. ;/******************************/
  1805. ;
  1806. ;   line printer driver
  1807. ;   with tab compression/expansion
  1808. ;
  1809. ;/******************************/
  1810.  
  1811. lptab:    mvi    e,@tab        ;print out tab
  1812. ;    jmp    lpdvd
  1813.  
  1814. lpdvd:    push    psw
  1815.     push    h
  1816.     call    cksumo        ;summary option wanted?
  1817.     jnz    lpdvd3        ;if yes, don't print out char
  1818.     lxi    h,col        ;^ column counter
  1819.     mov    a,e        ;get char to output
  1820.     sta    char        ;save for later
  1821.     cpi    ' '        ;is it a blank?
  1822.     jz    lpdvd8        ;if yes
  1823.     cpi    @tab        ;is it a tab
  1824.     jz    lpdvd4        ;if yes
  1825.     call    ckentab        ;enter tabs?
  1826.     mov    a,e        ;get character to output
  1827.     jz    lpdvd2        ;if no compression wanted
  1828.     mvi    e,' '        ;next char to print is a blank
  1829. lpdvd0:    mov    a,m        ;get column count
  1830.     inx    h        ;^ newcol
  1831.     sub    m        ;is col < newcol ?
  1832.     dcx    h        ;^ column
  1833.     jp    lpdvd1        ;if not, print out actual char
  1834.     call    pbyt        ;output blank
  1835.     inr    m        ;adj. column count
  1836.     jmp    lpdvd0        ;loop for more
  1837. lpdvd1:    lda    char        ;get original char to print out
  1838.     mov    e,a        ;set up registers 
  1839.     call    lpdvd9        ;smart print
  1840.     mov    a,m        ;get column count
  1841.     inx    h        ;^ newcol counter
  1842.     mov    m,a        ;save in newcount
  1843.     jmp    lpdvd3        ;exit routine
  1844. lpdvd2:    call    lpdvd9        ;smart print
  1845. lpdvd3:    pop    h        ;exit gracefully
  1846.     pop    psw
  1847.     ret
  1848.  
  1849. lpdvd4:    call    ckentab        ;enter tab option wanted?
  1850.     jnz    lpdvd6        ;if yes
  1851.     mvi    e,' '        ;else expand @tabs to blanks
  1852. lpdvd5:    call    pbyt        ;print out blank until tab stop
  1853.     inr    m        ;adjust column count
  1854.     mov    a,m        ;are we on a tab stop?
  1855.     ani    7        ;(modulo 8)
  1856.     jz    lpdvd3        ;exit if so
  1857.     jmp    lpdvd5        ;else, loop for more
  1858. lpdvd6:    inx    h        ;calculate next tab stop
  1859.     mov    a,m
  1860.     adi    8
  1861.     ani    -8
  1862.     mov    m,a
  1863. lpdvd7:    dcx    h        ;^ column counter
  1864.     mov    m,a        ;adjust column count to new position
  1865.     call    pbyt        ;print out @tab
  1866.     jmp    lpdvd3        ;exit routine
  1867. lpdvd8:    call    ckentab        ;enter tabs option wanted?
  1868.     mov    a,e        ;restore char to print
  1869.     jz    lpdvd2        ;if not, just print out & adj. column count
  1870.     inx    h        ;^ newcol counter
  1871.     inr    m        ;add one
  1872.     mov    a,m        ;are we on a tab stop?
  1873.     ani    7        ;(modulo 8)
  1874.     jnz    lpdvd3        ;if not on a tab stop, exit
  1875.     mov    a,m        ;get newcol count
  1876.     mvi    e,@tab        ;else, print out @tab
  1877.     jmp    lpdvd7        ;adj. column counter
  1878. lpdvd9:    call    ckpra        ;is character printable?
  1879.     call    pbyt        ;print-out anyway (for them "smart" printers)
  1880.     rc            ;so, wasn't printable, don't count
  1881.     inr    m        ;bump column count
  1882.     ret
  1883.  
  1884. ;/******************************/
  1885. ;
  1886. ;   print decimal string
  1887. ;   equivalent of HL
  1888. ;
  1889. ;/******************************/
  1890.  
  1891. prdec:    call    decotj        ;convert string to decimal
  1892.     lxi    h,dec        ;^ converted string
  1893. prde0:    call    getlc        ;get a char. from decimal string
  1894.     rc            ;when psw/c1, end of string so br out
  1895.     call    lpdvd        ;print out the char
  1896.     jmp    prde0        ;loop for more
  1897.  
  1898. ;/******************************/
  1899. ;
  1900. ;   get next char in line buffer
  1901. ;
  1902. ;/******************************/
  1903.  
  1904. getlc:    mov    e,m        ;get byte from buffer (^ by hl)
  1905.     mov    a,e        ;__into a and e
  1906.     inx    h        ;++ ^
  1907.     cpi    @cr        ;test for eol
  1908.     stc
  1909.     rz            ;__and return with psw/c1 if true
  1910.     cmc            ;__else reset psw/c0 if not
  1911.     ret            ;__and with read char in a and e
  1912.  
  1913. ;/******************************/
  1914. ;
  1915. ;   display current pass
  1916. ;   and line on console
  1917. ;
  1918. ;/******************************/
  1919.  
  1920. curpas:    lhld    lcnt        ;get current line#
  1921.     call    decotj        ;convert to decimal
  1922.     call    cdisp
  1923.     db    @cr,'Pass ',@nul
  1924.     call    ckpass        ;is it pass 1?
  1925.     jnz    curpas1        ;if yes
  1926.     call    cdisp        ;else, its pass 2
  1927.     db    '2 - ',@nul    ;so only print error lines
  1928.     lda    errl        ;is it an error line?
  1929.     ora    a        ;yes if not zero
  1930.     jnz    curpas2        ;print error line
  1931.     call    curpas2        ;display line number
  1932.     pop    h        ;don't print normal line
  1933.     ret            ;(return one level back)
  1934. curpas1:call    cdisp
  1935.     db    '1 - ',@nul
  1936. curpas2:call    cdisp
  1937.     db    'line # ',@nul
  1938.     push    d
  1939.     lxi    d,dec        ;display current line#
  1940.     call    psb        ;__to console
  1941.     pop    d
  1942. ;    jmp    pinit        ;return through pinit
  1943.  
  1944. ;/******************************/
  1945. ;
  1946. ;   init line buffer pointers
  1947. ;
  1948. ;/******************************/
  1949.  
  1950. pinit:    lxi    h,pbuf        ;reset ^ to start of line buffer
  1951.     shld    lpnt
  1952.     sub    a        ;reset column counters
  1953.     sta    col
  1954.     sta    newcol
  1955.     ret
  1956.  
  1957. ;/******************************/
  1958. ;
  1959. ;   collect symbol in sym buf
  1960. ;
  1961. ;/******************************/
  1962.  
  1963. gtsym:    call    mupc        ;map symbol to upper case
  1964.     mov    b,a        ;save char
  1965.     lda    symct        ;get symbol count
  1966.     cpi    symsiz        ;max?
  1967.     rnc            ;yes, done 
  1968.     inr    a
  1969.     sta    symct
  1970.     lhld    sympt
  1971.     mov    m,b
  1972.     inx    h        ;bump symbol pointer
  1973.     shld    sympt
  1974.     ret
  1975.  
  1976. ;/******************************/
  1977. ;
  1978. ;   printer interfaces
  1979. ;
  1980. ;/******************************/
  1981.  
  1982. pbyt:    push    psw        ;there goes the neighborhood...
  1983.     push    b
  1984.     push    d
  1985.     push    h
  1986.     call    ckcon        ;console trace option wanted?
  1987.     mov    a,e        ;get character to display
  1988.     cnz    fo
  1989.     call    ckdsk        ;disk output option wanted?
  1990.     jz    pbyt1        ;list to LST: if not
  1991.     mov    a,e        ;get character to save
  1992.     call    putfc        ;else, list to disk
  1993.     jmp    pbyt2        ;bypass printing
  1994. pbyt1:
  1995.     if    z8911
  1996.  
  1997. ;   heath h-89 with z-8911 extended i/o card device driver
  1998.  
  1999.     in    0d2h        ;status port of 8255
  2000.     ani    80h        ;ready?
  2001.     jz    pbyt1        ;loop if not
  2002.     mov    a,e        ;get byte to output
  2003.     out    0d0h        ;data port of 8255
  2004.     xra    a        ;turn strobe on (active low for tally 1602a)
  2005.     out    0d2h        ;do it
  2006.     inr    a        ;turn strobe off
  2007.     out    0d2h        ;do it again
  2008.  
  2009.     if    debug
  2010.     mvi    c,conof
  2011.     call    bdos
  2012.     endif            ;debug
  2013.  
  2014.     else            ;if not z8911
  2015.  
  2016.     if    debug
  2017.     mvi    c,conof
  2018.     else            ;if not debug
  2019.     mvi    c,listf        ;then use CP/M to perform
  2020.     endif            ;debug
  2021.  
  2022.     call    bdos        ;printer (list) out function
  2023.  
  2024.     endif            ;z8911
  2025.  
  2026. pbyt2:    call    break        ;check for console input
  2027.     pop    h        ;restore environment
  2028.     pop    d
  2029.     pop    b
  2030.     pop    psw
  2031.     ret
  2032.  
  2033. ;/*****************************/
  2034. ;
  2035. ;   check for console input
  2036. ;
  2037. ;/*****************************/
  2038.  
  2039. break:    mvi    c,constf    ;any pending char?
  2040.     call    bdos
  2041.     ora    a
  2042.     rz            ;if not
  2043.  
  2044. ;   Kluge to fix a minor bug in the direct console i/o  of CP/M 2.2 BDOS.
  2045. ;   Console status of  DCIO  function will  not reliably  detect the next
  2046. ;   typed  in  character  due  to  the  occurence of a 'pseudo-parrallel'
  2047. ;   routine (in BDOS) which  also  checks  console status,  and saves the
  2048. ;   input  character if one available.  This problem seems to appear more
  2049. ;   frequently when the console i/o  routines  are  interrupt  driven and
  2050. ;   shows up when a key  is struck during disk i/o. This 'lost' character
  2051. ;   reappears at the CCP prompt when the transient terminates.
  2052.  
  2053.     if    cpm22
  2054.     lda    warning
  2055.     ora    a
  2056.     jnz    break0        ;in case its not v2.2
  2057.     lhld    lastci        ;get ^ to lastci variable (in BDOS)
  2058.     mov    a,m        ;get last char input
  2059.     mvi    m,0        ;toggle flag
  2060.     ora    a        ;any char present?
  2061.     cz    dcin        ;if not, get it
  2062.     jmp    break1
  2063.     endif            ;cpm22
  2064.  
  2065. break0:    mvi    c,conif        ;problem with this approach is
  2066.     call    bdos        ;__that it echoes all displayable chars
  2067.  
  2068. break1:    cpi    'C'-40h        ;abort?
  2069.     rnz            ;if not return with char in a
  2070.     lda    quiet        ;temporarily disable quiet option
  2071.     push    psw
  2072.     call    fcdisp        ;ask confirmation if abort
  2073.  
  2074.     if    h19
  2075.     db    @esc,'y5'    ;re-enable cursor
  2076.     endif            ;h19
  2077.  
  2078.     db    @cr,@bel,'Abort? (Y/N or ^C to reboot) ',@nul
  2079.     mvi    c,conif        ;get input and echo
  2080.     call    bdos
  2081.     call    mupc        ;map to upper case
  2082.     cpi    'C'-40h        ;reboot?
  2083.     jnz    break2        ;if not
  2084.     call    cdisp        ;echo '^C' on console
  2085.     db    '^C',@nul
  2086.     jmp    wboot        ;exit back to CP/M
  2087. break2:    cpi    'Y'        ;abort? (w/o reboot)
  2088.     push    psw
  2089.     call    cdisp        ;crlf to screen
  2090.     db    @cr,@lf,@nul
  2091.     pop    psw
  2092.     jz    abort        ;if yes, terminate program
  2093.  
  2094.     if    h19
  2095.     call    cdisp
  2096.     db    @esc,'x5',@nul    ;else, disable cursor
  2097.     endif            ;h19
  2098.  
  2099.     pop    psw        ;restore quiet option  
  2100.     sta    quiet        ;__to original value
  2101.     ret            ;and ignore typed in char
  2102.  
  2103. ;/******************************/
  2104. ;
  2105. ;   unadorned console input
  2106. ;
  2107. ;/******************************/
  2108.  
  2109. dcin:    mvi    e,-1        ;set for input
  2110.     mvi    c,dciof        ;direct console i/o
  2111.     call    bdos        ;do it
  2112.     ora    a        ;set psw
  2113.     ret
  2114.  
  2115. ;/******************************/
  2116. ;
  2117. ;   initialize parallel port
  2118. ;
  2119. ;/******************************/
  2120.  
  2121.     if    z8911
  2122. in8255:    mvi    a,0aah        ;set up 8255 device
  2123.     out    0d3h
  2124.     mvi    a,1        ;set strobe off
  2125.     out    0d2h
  2126.     ret
  2127.     endif
  2128.  
  2129. ;/*******************************/
  2130. ;
  2131. ;   issue formf eject
  2132. ;
  2133. ;/*******************************/
  2134.  
  2135. formf:    push    psw
  2136.     sub    a        ;reset page line count
  2137.     sta    lines
  2138.     call    cksumo        ;is summary option active?
  2139.     jnz    formf0        ;if yes, don't print
  2140.     push    d
  2141.     mvi    e,@ff
  2142.     call    pbyt
  2143.     pop    d
  2144. formf0:    pop    psw
  2145.     ret
  2146.  
  2147. ;/******************************/
  2148. ;
  2149. ;   issue cr, lf & test formf
  2150. ;
  2151. ;/******************************/
  2152.  
  2153. crlf2:    call    crlft
  2154. crlft:    push    psw
  2155.     call    crlf        ;print out a cr & lf
  2156.     lda    lines        ;++ line counter
  2157.     inr    a
  2158.     sta    lines
  2159.     cpi    pglen        ;check for page eject
  2160.     cz    formf        ;__at every n lines printed
  2161.     call    pinit
  2162.     pop    psw
  2163.     ret
  2164.  
  2165. crlf:    push    psw
  2166.     call    cksumo        ;is summary option active?
  2167.     jnz    crlf0        ;if yes, don't print
  2168.     push    d
  2169.     mvi    e,@lf        ;print out @lf
  2170.     call    pbyt
  2171.     mvi    e,@cr        ;print out @cr
  2172.     call    pbyt
  2173.     pop    d
  2174. crlf0:    pop    psw
  2175.     ret
  2176.  
  2177. ;/******************************/
  2178. ;
  2179. ;   character parsing table
  2180. ;
  2181. ;/******************************/
  2182.  
  2183. ctab:    db    @lf
  2184.     dw    llf
  2185.     db    @ff
  2186.     dw    lff
  2187.     db    @cr
  2188.     dw    lcr
  2189.     db    ''''
  2190.     dw    lapos
  2191.  
  2192.     if    tdl
  2193.     db    '"'
  2194.     dw    lquot
  2195.     endif            ;tdl
  2196.  
  2197.     db    ';'
  2198.     dw    lsemi
  2199.  
  2200. ;   special symbol characters for Digital Research's MAC macro assembler
  2201.  
  2202.     if    mac
  2203.     db    '@'
  2204.     dw    lalph
  2205.     db    '?'
  2206.     dw    lalph
  2207.     endif            ;mac
  2208.  
  2209. ;   special symbols characters for TDL's macro assembler
  2210.  
  2211.     if    tdl
  2212.     db    '$'
  2213.     dw    lalph
  2214.     db    '%'
  2215.     dw    lalph
  2216.     db    '.'
  2217.     dw    ldot
  2218.     endif            ;tdl
  2219.  
  2220. ;   end of table
  2221.  
  2222.     db    eof
  2223. way:    dw    done
  2224.  
  2225. ;   this character should never be encountered in a normal .PRN file
  2226.  
  2227.     db    -1
  2228.     dw    former
  2229.  
  2230. ;/******************************/
  2231. ;
  2232. ;   reserved word table
  2233. ;
  2234. ;/******************************/
  2235.  
  2236. rtab:
  2237.     if    mac
  2238.     db    'A     '
  2239.     db    'ACI   '
  2240.     db    'ADC   '
  2241.     db    'ADD   '
  2242.     db    'ADI   '
  2243.     db    'ANA   '
  2244.     db    'AND   '
  2245.     db    'ANI   '
  2246.     db    'ASEG  '    ;reserved for RMAC
  2247.     db    'B     '
  2248.     db    'C     '
  2249.     db    'CALL  '
  2250.     db    'CC    '
  2251.     db    'CM    '
  2252.     db    'CMA   '
  2253.     db    'CMC   '
  2254.     db    'CMP   '
  2255.     db    'CNC   '
  2256.     db    'CNZ   '
  2257.     db    'CP    '
  2258.     db    'CPE   '
  2259.     db    'CPI   '
  2260.     db    'CPO   '
  2261.     db    'CSEG  '    ;reserved for RMAC
  2262.     db    'CZ    '
  2263.     db    'D     '
  2264.     db    'DAA   '
  2265.     db    'DAD   '
  2266.     db    'DB    '
  2267.     db    'DCR   '
  2268.     db    'DCX   '
  2269.     db    'DI    '
  2270.     db    'DS    '
  2271.     db    'DSEG  '    ;reserved for RMAC
  2272.     db    'DW    '
  2273.     db    'E     '
  2274.     db    'EI    '
  2275.     db    'ELSE  '    ;reserved for MAC
  2276.     db    'END   '
  2277.     db    'ENDIF '
  2278.     db    'ENDM  '    ;reserved for MAC
  2279.     db    'EQ    '
  2280.     db    'EQU   '
  2281.     db    'EXITM '    ;reserved for MAC
  2282.     db    'EXTRN '    ;reserved for RMAC
  2283.     db    'GE    '
  2284.     db    'GT    '
  2285.     db    'H     '
  2286.     db    'HIGH  '
  2287.     db    'HLT   '
  2288.     db    'IF    '
  2289.     db    'IN    '
  2290.     db    'INPAGE'    ;reserved for RMAC
  2291.     db    'INR   '
  2292.     db    'INX   '
  2293.     db    'IRP   '    ;reserved for MAC
  2294.     db    'IRPC  '    ;reserved for MAC
  2295.     db    'JC    '
  2296.     db    'JM    '
  2297.     db    'JMP   '
  2298.     db    'JNC   '
  2299.     db    'JNZ   '
  2300.     db    'JP    '
  2301.     db    'JPE   '
  2302.     db    'JPO   '
  2303.     db    'JZ    '
  2304.     db    'L     '
  2305.     db    'LDA   '
  2306.     db    'LDAX  '
  2307.     db    'LE    '
  2308.     db    'LHLD  '
  2309.     db    'LOCAL '    ;reserved for MAC
  2310.     db    'LOW   '
  2311.     db    'LT    '
  2312.     db    'LXI   '
  2313.     db    'M     '
  2314.     db    'MACLIB'    ;reserved for MAC
  2315.     db    'MACRO '    ;reserved for MAC
  2316.     db    'MOD   '
  2317.     db    'MOV   '
  2318.     db    'MVI   '
  2319.     db    'NAME  '    ;reserved for RMAC
  2320.     db    'NE    '
  2321.     db    'NOP   '
  2322.     db    'NOT   '
  2323.     db    'NUL   '
  2324.     db    'OR    '
  2325.     db    'ORA   '
  2326.     db    'ORG   '
  2327.     db    'ORI   '
  2328.     db    'OUT   '
  2329.     db    'PAGE  '
  2330.     db    'PCHL  '
  2331.     db    'POP   '
  2332.     db    'PSW   '
  2333.     db    'PUBLIC'    ;reserved for RMAC
  2334.     db    'PUSH  '
  2335.     db    'RAL   '
  2336.     db    'RAR   '
  2337.     db    'RC    '
  2338.     db    'REPT  '    ;reserved for MAC
  2339.     db    'RET   '
  2340.     db    'RLC   '
  2341.     db    'RM    '
  2342.     db    'RNC   '
  2343.     db    'RNZ   '
  2344.     db    'RP    '
  2345.     db    'RPE   '
  2346.     db    'RPO   '
  2347.     db    'RRC   '
  2348.     db    'RST   '
  2349.     db    'RZ    '
  2350.     db    'SBB   '
  2351.     db    'SBI   '
  2352.     db    'SET   '
  2353.     db    'SHL   '
  2354.     db    'SHLD  '
  2355.     db    'SHR   '
  2356.     db    'SP    '
  2357.     db    'SPHL  '
  2358.     db    'STA   '
  2359.     db    'STAX  '
  2360.     db    'STC   '
  2361.     db    'STKLN '    ;reserved for RMAC
  2362.     db    'SUB   '
  2363.     db    'SUI   '
  2364.     db    'TITLE '    ;reserved for MAC
  2365.     db    'XCHG  '
  2366.     db    'XOR   '
  2367.     db    'XRA   '
  2368.     db    'XRI   '
  2369.     db    'XTHL  '
  2370.     endif            ;mac
  2371.  
  2372.     if    tdl
  2373.     db    '.     '    ;'.' is a legal global symbol
  2374.                 ;__that in my opinion can lead to confusion
  2375.     db    '.ASCII'
  2376.     db    '.ASCIS'
  2377.     db    '.ASCIZ'
  2378.     db    '.BLKB '
  2379.     db    '.BLKW '
  2380.     db    '.BYTE '
  2381.     db    '.DATE '    ;reserved for MACRO_III
  2382.     db    '.DEFIN'
  2383.     db    '.END  '
  2384.     db    '.ENTRY'
  2385.     db    '.ERROR'
  2386.     db    '.EXIT '
  2387.     db    '.EXTER'
  2388.     db    '.GOTO '
  2389.     db    '.I8080'
  2390.     db    '.IDENT'
  2391.     db    '.IF1  '
  2392.     db    '.IF2  '
  2393.     db    '.IFB  '
  2394.     db    '.IFDEF'
  2395.     db    '.IFDIF'
  2396.     db    '.IFE  '
  2397.     db    '.IFG  '
  2398.     db    '.IFGE '
  2399.     db    '.IFIDN'
  2400.     db    '.IFL  '
  2401.     db    '.IFLE '
  2402.     db    '.IFN  '
  2403.     db    '.IFNB '
  2404.     db    '.IFNDE'
  2405.     db    '.INSER'
  2406.     db    '.INTER'
  2407.     db    '.LADDR'
  2408.     db    '.LALL '
  2409.     db    '.LCTL '
  2410.     db    '.LIMAG'
  2411.     db    '.LINK '
  2412.     db    '.LIST '
  2413.     db    '.LOC  '
  2414.     db    '.LSYM '
  2415.     db    '.MASYN'
  2416.     db    '.OPSYN'
  2417.     db    '.PABS '
  2418.     db    '.PAGE '
  2419.     db    '.PBIN '
  2420.     db    '.PHEX '
  2421.     db    '.PREL '
  2422.     db    '.PRGEN'
  2423.     db    '.PRNTX'
  2424.     db    '.PROGI'
  2425.     db    '.PSYM '
  2426.     db    '.RAD40'
  2427.     db    '.RADIX'
  2428.     db    '.RELOC'
  2429.     db    '.REMAR'
  2430.     db    '.RLIST'
  2431.     db    '.SALL '
  2432.     db    '.SBTTL'
  2433.     db    '.SETDA'    ;reserved for MACRO_III
  2434.     db    '.SETLE'    ;reserved for MACRO_III
  2435.     db    '.SETTI'    ;reserved for MACRO_III
  2436.     db    '.SETWI'    ;reserved for MACRO_III
  2437.     db    '.SLIST'
  2438.     db    '.SYN  '
  2439.     db    '.SYSYN'
  2440.     db    '.TEMPS'
  2441.     db    '.TIME '    ;reserved for MACRO_III
  2442.     db    '.TITLE'
  2443.     db    '.WORD '
  2444.     db    '.XADDR'
  2445.     db    '.XALL '
  2446.     db    '.XCTL '
  2447.     db    '.XIMAG'
  2448.     db    '.XLINK'
  2449.     db    '.XLIST'
  2450.     db    '.XPSYM'
  2451.     db    '.XSYM '
  2452.     db    '.Z80  '
  2453.     db    'A     '
  2454.     db    'ACI   '
  2455.     db    'ADC   '
  2456.     db    'ADD   '
  2457.     db    'ADI   '
  2458.     db    'ANA   '
  2459.     db    'ANI   '
  2460.     db    'B     '
  2461.     db    'BIT   '
  2462.     db    'C     '
  2463.     db    'CALL  '
  2464.     db    'CC    '
  2465.     db    'CCD   '
  2466.     db    'CCDR  '
  2467.     db    'CCI   '
  2468.     db    'CCIR  '
  2469.     db    'CM    '
  2470.     db    'CMA   '
  2471.     db    'CMC   '
  2472.     db    'CMP   '
  2473.     db    'CNC   '
  2474.     db    'CNO   '
  2475.     db    'CNZ   '
  2476.     db    'CO    '
  2477.     db    'CP    '
  2478.     db    'CPE   '
  2479.     db    'CPI   '
  2480.     db    'CPO   '
  2481.     db    'CZ    '
  2482.     db    'D     '
  2483.     db    'DAA   '
  2484.     db    'DAD   '
  2485.     db    'DADC  '
  2486.     db    'DADX  '
  2487.     db    'DADY  '
  2488.     db    'DCR   '
  2489.     db    'DCX   '
  2490.     db    'DI    '
  2491.     db    'DJNZ  '
  2492.     db    'DSBC  '
  2493.     db    'E     '
  2494.     db    'EI    '
  2495.     db    'EXAF  '
  2496.     db    'EXX   '
  2497.     db    'H     '
  2498.     db    'HLT   '
  2499.     db    'IM0   '
  2500.     db    'IM1   '
  2501.     db    'IM2   '
  2502.     db    'IN    '
  2503.     db    'IND   '
  2504.     db    'INDR  '
  2505.     db    'INI   '
  2506.     db    'INIR  '
  2507.     db    'INP   '
  2508.     db    'INR   '
  2509.     db    'INX   '
  2510.     db    'JC    '
  2511.     db    'JM    '
  2512.     db    'JMP   '
  2513.     db    'JMPR  '
  2514.     db    'JNC   '
  2515.     db    'JNO   '
  2516.     db    'JNZ   '
  2517.     db    'JO    '
  2518.     db    'JP    '
  2519.     db    'JPE   '
  2520.     db    'JPO   '
  2521.     db    'JRC   '
  2522.     db    'JRNC  '
  2523.     db    'JRNZ  '
  2524.     db    'JRZ   '
  2525.     db    'JZ    '
  2526.     db    'L     '
  2527.     db    'LBCD  '
  2528.     db    'LDA   '
  2529.     db    'LDAI  '
  2530.     db    'LDAR  '
  2531.     db    'LDAX  '
  2532.     db    'LDD   '
  2533.     db    'LDDR  '
  2534.     db    'LDED  '
  2535.     db    'LDI   '
  2536.     db    'LDIR  '
  2537.     db    'LHLD  '
  2538.     db    'LIXD  '
  2539.     db    'LIYD  '
  2540.     db    'LSPD  '
  2541.     db    'LXI   '
  2542.     db    'M     '
  2543.     db    'MOV   '
  2544.     db    'MVI   '
  2545.     db    'NEG   '
  2546.     db    'NOP   '
  2547.     db    'ORA   '
  2548.     db    'ORI   '
  2549.     db    'OUT   '
  2550.     db    'OUTD  '
  2551.     db    'OUTDR '
  2552.     db    'OUTI  '
  2553.     db    'OUTIR '
  2554.     db    'OUTP  '
  2555.     db    'P     '
  2556.     db    'PCHL  '
  2557.     db    'PCIX  '
  2558.     db    'PCIY  '
  2559.     db    'POP   '
  2560.     db    'PSW   '
  2561.     db    'PUSH  '
  2562.     db    'RAL   '
  2563.     db    'RALR  '
  2564.     db    'RAR   '
  2565.     db    'RARR  '
  2566.     db    'RC    '
  2567.     db    'RES   '
  2568.     db    'RET   '
  2569.     db    'RETI  '
  2570.     db    'RETN  '
  2571.     db    'RLC   '
  2572.     db    'RLCR  '
  2573.     db    'RLD   '
  2574.     db    'RM    '
  2575.     db    'RNC   '
  2576.     db    'RNO   '
  2577.     db    'RNZ   '
  2578.     db    'RO    '
  2579.     db    'RP    '
  2580.     db    'RPE   '
  2581.     db    'RPO   '
  2582.     db    'RRC   '
  2583.     db    'RRCR  '
  2584.     db    'RRD   '
  2585.     db    'RST   '
  2586.     db    'RZ    '
  2587.     db    'SBB   '
  2588.     db    'SBCD  '
  2589.     db    'SBI   '
  2590.     db    'SDED  '
  2591.     db    'SET   '
  2592.     db    'SHLD  '
  2593.     db    'SIXD  '
  2594.     db    'SIYD  '
  2595.     db    'SLAR  '
  2596.     db    'SP    '
  2597.     db    'SPHL  '
  2598.     db    'SPIX  '
  2599.     db    'SPIY  '
  2600.     db    'SRAR  '
  2601.     db    'SRLR  '
  2602.     db    'SSPD  '
  2603.     db    'STA   '
  2604.     db    'STAI  '
  2605.     db    'STAR  '
  2606.     db    'STAX  '
  2607.     db    'STC   '
  2608.     db    'SUB   '
  2609.     db    'SUI   '
  2610.     db    'X     '
  2611.     db    'XCHG  '
  2612.     db    'XRA   '
  2613.     db    'XRI   '
  2614.     db    'XTHL  '
  2615.     db    'Y     '
  2616.     endif            ;tdl
  2617.  
  2618.     db    -1        ;end of reserved word table
  2619.  
  2620. ;/******************************/
  2621. ;
  2622. ;   routine to open a disk file
  2623. ;
  2624. ;   in:        de=a(fcb)
  2625. ;   out:    fc/1=error
  2626. ;
  2627. ;/******************************/
  2628.  
  2629. fopen:    mvi    c,openf        ;open file function
  2630.     call    bdos        ;issue open
  2631.     cpi    -1        ;error?
  2632.     stc            ;set psw/c1 if so
  2633.     rz
  2634.     cmc            ;else clear carry
  2635.     ret
  2636.  
  2637. ;/******************************/
  2638. ;
  2639. ;   routine to close a disk file
  2640. ;
  2641. ;   in:        de=a(fcb)
  2642. ;
  2643. ;/******************************/
  2644.  
  2645. fclose:    mvi    c,closef
  2646.     jmp    bdos        ;return through BDOS
  2647.  
  2648. ;/******************************/
  2649. ;
  2650. ;   routine to read a byte
  2651. ;
  2652. ;   out:    a=byte
  2653. ;        fc/1=error
  2654. ;
  2655. ;/******************************/
  2656.  
  2657. getfc:    call    getbt        ;get a file character
  2658.     call    savbt        ;save it in line buffer
  2659.     jc    skipn0        ;in case of hard eof
  2660.     cpi    eof        ;__or soft eof
  2661.     jz    skipn0
  2662.     cpi    ' '        ;set psw/z1 if space
  2663.     ret
  2664.  
  2665. getbt:    push    b
  2666.     push    d
  2667.     push    h
  2668.     lhld    tbdma        ;get end of buffer
  2669.     xchg            ;to de
  2670.     lhld    inptr        ;current pointer in hl
  2671.     call    cphl        ;test for end of buffer
  2672.     jz    getb2        ;yes, read
  2673. getb1:    mov    a,m        ;get byte
  2674.     inx    h        ;bump pointer
  2675.     shld    inptr        ;save pointer
  2676.     ora    a        ;reset carry
  2677.     jmp    ierr1        ;exit
  2678. getb2:    lda    tbflg        ;get flag
  2679.     ora    a        ;test it
  2680.     jnz    ierr        ;br if no more
  2681.     lxi    h,tbuf-128    ;else set start of buffer
  2682.     mvi    a,tbsze        ;and buffer size in sectors
  2683. getb3:    sta    tbcnt        ;save it
  2684.     lxi    d,128        ;calculate new starting
  2685.     dad    d        ;address
  2686.     shld    tbdma        ;save it
  2687.     xchg            ;place it in de
  2688.     mvi    c,sdmaf        ;set dma address
  2689.     call    bdos
  2690.     mvi    c,readf        ;read code
  2691.     lxi    d,fcb        ;fcb address
  2692.     call    bdos        ;issue read
  2693.     ora    a        ;check for error/e-o-f
  2694.     jnz    getb4        ;br if so
  2695.     lhld    tbdma        ;else get last dma starting addr
  2696.     lda    tbcnt        ;get sector count
  2697.     dcr    a        ;subtract one
  2698.     jnz    getb3        ;br if some more
  2699.     lxi    d,128        ;else set new end of buffer
  2700.     dad    d
  2701.     shld    tbdma
  2702.     jmp    getb5
  2703. getb4:    mvi    a,-1        ;set flag
  2704.     sta    tbflg
  2705. getb5:    lxi    h,tbuf        ;reset buffer pointer
  2706.     jmp    getb1        ;continue
  2707.  
  2708. ierr:    stc
  2709. ierr1:    pop    h
  2710.     pop    d
  2711.     pop    b
  2712.     ret
  2713.  
  2714. ;/******************************/
  2715. ;
  2716. ;   routine to save a byte
  2717. ;
  2718. ;/******************************/
  2719.  
  2720. putfc:    cpi    eof
  2721.     jz    putfc1
  2722.     call    writec
  2723.     ret
  2724. putfc1:    call    writec
  2725. putfc2:    lda    bufadd
  2726.     cpi    128
  2727.     rz
  2728.     mvi    a,eof
  2729.     call    writec
  2730.     jmp    putfc2
  2731.  
  2732. ;/******************************/
  2733. ;
  2734. ;   write a character to disk
  2735. ;
  2736. ;/******************************/
  2737.  
  2738. writec:    push    h
  2739.     lhld    bufadd
  2740.     mov    m,a
  2741.     inx    h
  2742.     sub    a
  2743.     cmp    l
  2744.     cz    newrit
  2745.     shld    bufadd
  2746.     pop    h
  2747.     ret
  2748.  
  2749. newrit:    lxi    h,dma
  2750.     push    h
  2751.     push    d
  2752.     push    b
  2753.     push    psw
  2754.     xchg
  2755.     mvi    c,sdmaf        ;set dma address
  2756.     call    bdos
  2757.     lxi    d,dfcb
  2758.     mvi    c,writef
  2759.     call    bdos        ;write one record
  2760.     ora    a        ;write okay?
  2761.     jz    wexit        ;if yes
  2762.     call    fcdisp
  2763.     db    @bel,'+++ disk full +++ ',@nul
  2764.     jmp    abort
  2765.  
  2766. wexit:    pop    psw
  2767.     pop    b
  2768.     pop    d
  2769.     pop    h
  2770.     ret
  2771.  
  2772. ;/******************************/
  2773. ;
  2774. ;             c p h l
  2775. ;   routine to compare hl vs de
  2776. ;
  2777. ;/******************************/
  2778.  
  2779. cphl:    mov    a,h
  2780.     cmp    d
  2781.     rnz
  2782.     mov    a,l
  2783.     cmp    e
  2784.     ret
  2785.  
  2786. ;/*****************************/
  2787. ;
  2788. ;   word to decimal conversion
  2789. ;
  2790. ;/*****************************/
  2791.  
  2792. decout:    push    psw
  2793.     push    b
  2794.     push    d
  2795.     push    h
  2796.     lxi    b,-10        ;radix for conversion
  2797.     lxi    d,-1        ;becomes number/radix
  2798. decou1:    dad    b        ;substract 10
  2799.     inx    d
  2800.     jc    decou1
  2801.     lxi    b,10        ;add radix back in once
  2802.     dad    b
  2803.     xchg
  2804.     mov    a,h        ;test for zero
  2805.     ora    l
  2806.     cnz    decout        ;elegant recursive call
  2807.     mov    a,e
  2808.     adi    '0'        ;convert from bcd to hex
  2809.     call    co        ;display
  2810.     pop    h
  2811.     pop    d
  2812.     pop    b
  2813.     pop    psw
  2814.     ret
  2815.  
  2816. ;/******************************/
  2817. ;
  2818. ;   inline message display
  2819. ;
  2820. ;/******************************/
  2821.  
  2822. ildisp:    xthl            ;get ^string from stack
  2823. ildis1:    mov    a,m        ;get a byte
  2824.     inx    h        ;bump ^
  2825.     ora    a        ;test for delimiter
  2826.     push    psw
  2827.     push    d
  2828.     push    h
  2829.     lxi    h,ildis2    ;set indirect 
  2830.     push    h        ;return address on stack
  2831.     xchg            ;get routine address
  2832.     pchl            ;indirect call
  2833. ildis2:    pop    h
  2834.     pop    d
  2835.     pop    psw
  2836.     jnz    ildis1        ;loop till done
  2837.     xthl            ;restore proper return address
  2838.     ret
  2839.  
  2840. ;/******************************/
  2841. ;
  2842. ;   print message on both
  2843. ;   console and line printer
  2844. ;
  2845. ;/******************************/
  2846.  
  2847. lcdisp:    lxi    d,lcdisp1
  2848.     jmp    ildisp
  2849. lcdisp1:mov    e,a
  2850.     call    lpdvd
  2851.     jmp    co        ;indirect return through co
  2852.  
  2853. ;/******************************/
  2854. ;
  2855. ;   print message to line printer
  2856. ;
  2857. ;/******************************/
  2858.  
  2859. ldisp:    lxi    d,ldis1
  2860.     jmp    ildisp
  2861. ldis1:    mov    e,a
  2862.     jmp    lpdvd        ;indirect return through lpdvd
  2863.  
  2864. ;/******************************/
  2865. ;
  2866. ;   force display of
  2867. ;   message on console
  2868. ;
  2869. ;/******************************/
  2870.  
  2871. fcdisp:    sub    a        ;deactivate quiet option
  2872.     sta    quiet
  2873. ;    jmp    cdisp        ;return through cdisp
  2874.  
  2875. ;/******************************/
  2876. ;
  2877. ;   conditional display of
  2878. ;   message on console
  2879. ;
  2880. ;/******************************/
  2881.  
  2882. cdisp:    lxi    d,co        ;indirect return through co
  2883.     jmp    ildisp
  2884.  
  2885. ;/******************************/
  2886. ;
  2887. ;   output character to console
  2888. ;
  2889. ;/******************************/
  2890.  
  2891. co:    push    psw
  2892.     call    ckquiet
  2893.     jz    co0
  2894.     pop    psw
  2895.     ret
  2896. co0:    pop    psw
  2897. ;    jmp    fo
  2898.  
  2899. fo:    push    psw
  2900.     push    b
  2901.     push    d
  2902.     push    h
  2903.     mov    e,a
  2904.     mvi    c,conof
  2905.     call    bdos
  2906.     pop    h
  2907.     pop    d
  2908.     pop    b
  2909.     pop    psw
  2910.     ret
  2911.  
  2912. ;/******************************/
  2913. ;
  2914. ; print string buffer to console
  2915. ;
  2916. ;/******************************/
  2917.  
  2918. psb:    push    psw
  2919.     push    b
  2920.     push    d
  2921.     push    h
  2922.     mvi    c,psbf
  2923.     call    ckquiet
  2924.     cz    bdos
  2925.     pop    h
  2926.     pop    d
  2927.     pop    b
  2928.     pop    psw
  2929.     ret
  2930.  
  2931. ;/******************************/
  2932. ;
  2933. ;   banner print routine
  2934. ;
  2935. ;/******************************/
  2936.  
  2937. banner:
  2938.     if    eject
  2939.     call    formf        ;start on fresh page
  2940.     endif            ;eject
  2941.  
  2942.     call    ckban        ;banner wanted or not?
  2943.     rnz            ;just return if not
  2944.     call    bannes
  2945.     jmp    formf        ;return through formf
  2946.  
  2947. bannes:    if    mac
  2948.     mvi    b,8        ;__8 lines down
  2949.     endif            ;mac
  2950.  
  2951.     if    tdl
  2952.     mvi    b,9
  2953.     endif            ;tdl
  2954.  
  2955. bannel:    call    crlf
  2956.     dcr    b
  2957.     jnz    bannel
  2958.     call    mvfcb        ;get converted fcb
  2959. banne0:    mvi    d,40h        ;init d for matrix of 7 vertical
  2960.     lxi    h,pbuf        ;define buffer area
  2961. banne1:    shld    banc        ;save ^char. buffer
  2962.     mov    a,m        ;get char from buffer
  2963.     ani    7fh        ;strip off r/o bit
  2964.     mov    m,a        ;__for good
  2965.     cpi    @cr        ;end of record?
  2966.     jz    banne2        ; finish full expansion if so
  2967.     call    cvpix        ; no, link char. to graphics
  2968.     cnc    banexp        ;if legal, expand first scan of pixels
  2969.     lhld    banc        ;restore ^char.
  2970.     inx    h        ;++^
  2971.     jmp    banne1        ;loop till done
  2972.  
  2973. ;   print out full characters expansion
  2974.  
  2975. banne2:    call    crlf        ;print out line and start a fresh one
  2976.     mov    a,d
  2977.     rar
  2978.     ani    7fh
  2979.     rz            ;exit when done
  2980.     mov    d,a
  2981. banne3:    lxi    h,pbuf        ;reset to start of buffer
  2982. banne4:    shld    banc        ;save ^char.
  2983.     mov    a,m        ;get char.
  2984.     cpi    @cr        ;record end?
  2985.     jz    banne2        ;expand all if so
  2986.     call    cvpix        ;link char. to graph.
  2987.     cnc    banexp        ;if legal, print another scan
  2988.     lhld    banc        ;get ^char.
  2989.     inx    h        ;++^
  2990.     jmp    banne4        ;loop till done
  2991.  
  2992. ;   convert characters to graphics
  2993.  
  2994. cvpix:    push    h        ;save ^
  2995.     call    cvpi2        ;link ^ ;cy = invalid
  2996.     jc    cvpi1        ;if error, restore original ^
  2997.     xthl            ;else save link ^ on stack
  2998. cvpi1:    pop    h        ;restore stack into hl
  2999.     ret
  3000.  
  3001. cvpi2:    mov    e,a
  3002.     sui    ' '
  3003.     rc
  3004.     lxi    h,0
  3005.     jz    cvpi4
  3006.     sui    '*'-' '
  3007.     rc
  3008.     cpi    'Z'+1-'*'
  3009.     jnc    cvpi5
  3010.     adi    1
  3011.     mvi    b,0
  3012.     mov    c,a
  3013.     mov    l,a
  3014.     dad    h        ;1x*2 = 2x
  3015.     dad    b        ;2x+x = 3x
  3016.     dad    h        ;3x*2 = 6x
  3017.     dad    b        ;6x+x = 7x
  3018. cvpi4:    lxi    b,pixtab
  3019.     dad    b
  3020.     ret
  3021. cvpi5:    adi    -1
  3022.     ret
  3023.  
  3024. ;   expand and print out graphics
  3025.  
  3026. banexp:    mvi    c,7        ;set #of pixels per char
  3027. banex1:    shld    banp
  3028.     mov    a,m
  3029.     ana    a
  3030.     jm    banex3
  3031.     mov    b,e
  3032.     ana    d
  3033.     jnz    banex2
  3034.     mvi    b,' '
  3035. banex2:    push    b
  3036.     push    d
  3037.     mov    e,b
  3038.     call    pbyt
  3039.     pop    d
  3040.     pop    b
  3041.     lhld    banp
  3042.     inx    h
  3043.     dcr    c
  3044.     jnz    banex1
  3045. banex3:    mvi    b,' '
  3046.     push    b
  3047.     push    d
  3048.     mov    e,b
  3049.     call    pbyt
  3050.     call    pbyt
  3051.     call    pbyt
  3052.     pop    d
  3053.     pop    b
  3054.     ret
  3055.  
  3056. ;/******************************/
  3057. ;
  3058. ;   xfer justified fcb
  3059. ;
  3060. ;/******************************/
  3061.  
  3062. mvfcb:    lxi    h,pbuf        ;^ destination
  3063.     push    h        ;save ^
  3064.     lxi    d,fcb+1        ;^ source
  3065.     mvi    b,8        ;max file name length
  3066.     call    move        ;perform transfer
  3067.     pop    h        ;restore ^ destination
  3068.     mvi    a,' '        ;prepare to justify (filter spaces)
  3069.     mvi    b,8        ;safeguard
  3070. mvfc0:    cmp    m        ;test for first space
  3071.     jz    mvfc1        ;exit loop when hit
  3072.     inx    h        ;bump ^
  3073.     dcr    b        ;in case 8 chars used in fn.
  3074.     jnz    mvfc0        ;loop for more
  3075. mvfc1:    mvi    m,'.'        ;insert a dot
  3076.     inx    h        ;bump ^
  3077.     mvi    b,3        ;max extent length
  3078.     call    move        ;xfer again
  3079.     mvi    m,@cr        ;save delimiter
  3080.     ret
  3081.  
  3082. ;/******************************/
  3083. ;
  3084. ;   graphics pixels table
  3085. ;
  3086. ;/******************************/
  3087.  
  3088. pixtab:    db    00h,00h,00h,00h,00h,00h,00h    ;null
  3089.     db    08h,22h,08h,1ch,08h,22h,08h    ; *
  3090.     db    08h,08h,08h,3eh,08h,08h,08h    ; +
  3091.     db    03h,80h,80h,80h,80h,80h,80h    ; ,
  3092.     db    08h,08h,08h,08h,08h,80h,80h    ; -
  3093.     db    01h,80h,80h,80h,80h,80h,80h    ; .
  3094.     db    01h,02h,04h,08h,10h,20h,40h    ; /
  3095.     db    3eh,43h,45h,49h,51h,61h,3eh    ; 0
  3096.     db    01h,11h,31h,7fh,01h,01h,01h    ; 1
  3097.     db    20h,41h,43h,45h,49h,51h,21h    ; 2
  3098.     db    22h,41h,49h,49h,49h,49h,36h    ; 3
  3099.     db    04h,0ch,14h,24h,44h,0fh,04h    ; 4
  3100.     db    7ah,49h,49h,49h,49h,49h,46h    ; 5
  3101.     db    3eh,49h,49h,49h,49h,49h,26h    ; 6
  3102.     db    41h,42h,44h,48h,50h,60h,40h    ; 7
  3103.     db    36h,49h,49h,49h,49h,49h,36h    ; 8
  3104.     db    32h,49h,49h,49h,49h,49h,3eh    ; 9
  3105.     db    12h,80h,80h,80h,80h,80h,80h    ; :
  3106.     db    13h,80h,80h,80h,80h,80h,80h    ; ;
  3107.     db    08h,14h,22h,41h,41h,41h,80h    ; <
  3108.     db    14h,14h,14h,14h,14h,14h,14h    ; =
  3109.     db    41h,41h,41h,22h,14h,08h,80h    ; >
  3110.     db    20h,40h,40h,4dh,48h,50h,20h    ; ?
  3111.     db    3eh,41h,41h,49h,55h,55h,39h    ; @
  3112.     db    3fh,48h,48h,48h,48h,48h,3fh    ; A
  3113.     db    7fh,49h,49h,49h,49h,49h,36h    ; B
  3114.     db    3eh,41h,41h,41h,41h,41h,22h    ; C
  3115.     db    7fh,41h,41h,41h,41h,41h,3eh    ; D
  3116.     db    7fh,49h,49h,49h,49h,49h,41h    ; E
  3117.     db    7fh,48h,48h,48h,48h,48h,40h    ; F
  3118.     db    3eh,41h,41h,41h,4dh,49h,2eh    ; G
  3119.     db    7fh,08h,08h,08h,08h,08h,7fh    ; H
  3120.     db    41h,41h,41h,7fh,41h,41h,41h    ; I
  3121.     db    06h,01h,01h,01h,41h,7eh,40h    ; J
  3122.     db    7fh,08h,08h,08h,14h,22h,41h    ; K
  3123.     db    7fh,01h,01h,01h,01h,01h,01h    ; L
  3124.     db    7fh,20h,10h,08h,10h,20h,7fh    ; M
  3125.     db    7fh,20h,10h,08h,04h,02h,7fh    ; N
  3126.     db    3eh,41h,41h,41h,41h,41h,3eh    ; O
  3127.     db    7fh,48h,48h,48h,48h,48h,30h    ; P
  3128.     db    3eh,41h,41h,45h,45h,42h,3dh    ; Q
  3129.     db    7fh,48h,48h,4ch,4ah,4ah,31h    ; R
  3130.     db    32h,49h,49h,49h,49h,49h,26h    ; S
  3131.     db    40h,40h,40h,7fh,40h,40h,40h    ; T
  3132.     db    7eh,01h,01h,01h,01h,01h,7eh    ; U
  3133.     db    70h,0ch,02h,01h,02h,0ch,70h    ; V
  3134.     db    7fh,02h,04h,08h,04h,02h,7fh    ; W
  3135.     db    41h,22h,14h,08h,14h,22h,41h    ; X
  3136.     db    60h,10h,08h,07h,08h,10h,60h    ; Y
  3137.     db    41h,43h,45h,49h,51h,61h,41h    ; Z
  3138.  
  3139. ;/******************************/
  3140. ;
  3141. ;   miscellaneous data
  3142. ;
  3143. ;/******************************/
  3144.  
  3145. symbt:    dw    0        ;symbol table bottom address
  3146. symtp:    dw    0        ;symbol table top address
  3147. refbt:    dw    0        ;reference table bottom address
  3148. reftp:    dw    0        ;reference table top address
  3149. sym:    dw    0        ;current symbol table address
  3150. ref:    dw    0        ;current reference table address
  3151. from:    dw    0        ;move pointer
  3152. to:    dw    0        ;to pointer
  3153. limit:    dw    0        ;limit pointer
  3154. col:    db    0        ;current line column position
  3155. newcol:    db    0        ;for tabs compression
  3156. char:    db    0        ;last read character
  3157. errl:    db    0        ;error line flag
  3158. lcnt:    dw    0        ;line counter
  3159. errorc:    dw    0        ;error counter
  3160. lpnt:    dw    0        ;line buffer char ^
  3161. lastp:    dw    0        ;previous line number variable
  3162. symct:    db    0        ;symbol count
  3163. sympt:    dw    0        ;symbol ^
  3164. lines:    db    0        ;print line count
  3165. temp:    dw    0        ;temporary variable
  3166. tbflg:    db    0        ;transient buffer flag (00=more, ff=no more)
  3167. tbcnt:    db    0        ;transient buffer sector count
  3168. tbdma:    dw    0        ;dma end of buffer address
  3169. inptr:    dw    0        ;input pointer
  3170. bufadd:    dw    0        ;output pointer
  3171. banc:    dw    0        ;banner character pointer
  3172. banp:    dw    0        ;banner pixel pointer
  3173. pass:    db    0        ;current pass flag
  3174. crt:    db    0        ;CON: trace option flag
  3175. diskl:    db    0        ;disk output option flag
  3176. error:    db    0        ;error only option flag
  3177. nobanr:    db    0        ;no banner option flag
  3178. quiet:    db    0        ;quiet operation flag
  3179. summary:db    0        ;summary option flag
  3180. entab:    db    0        ;compress tabs option flag
  3181. warning:db    0        ;CP/M 2.2 BDOS flag
  3182. lastci:    dw    0        ;vector to last char entered (in BDOS 2.2)
  3183. ifcb:    rept    fcbl        ;initial fcb copy
  3184.     db    0
  3185.     endm
  3186. dfcb:    rept    fcbl        ;destination fcb
  3187.     db    0
  3188.     endm
  3189. dec:    rept    digits        ;right justified line # string
  3190.     db    0
  3191.     endm
  3192.     db    @cr,'$'
  3193. sbuf    set    $        ;symbol buffer
  3194. pbuf    set    sbuf+symsiz    ;line buffer
  3195. stack    set    pbuf+132+100h    ;local stack area
  3196. tbuf    set    stack        ;transient buffer
  3197.  
  3198. ;/*********************************/
  3199. ;
  3200. ;        symbol table area
  3201. ;
  3202. ;   the symbol table must be the
  3203. ;   last location of the program
  3204. ;
  3205. ;/*********************************/
  3206.  
  3207. symt    set    tbuf+(tbsze*128)
  3208.  
  3209.     end    tpa
  3210.