Subversion Repositories NedoOS

Rev

Rev 630 | Go to most recent revision | Blame | Compare with Previous | Last modification | View Log | Download

  1. ;
  2. ; CCB.ASM: Second main source file of CC.ASM
  3. ;
  4. ;       Miscellaneious utility routines,
  5. ;
  6.  
  7.  
  8. ;
  9. ; Delete a file:
  10. ;
  11.  
  12.         IF CPM
  13. delfil:
  14.         ld de,fcb
  15. delf2:
  16.         push hl
  17.         push de
  18.         ld hl,12
  19.         add hl,de
  20.         ld (hl),0
  21.         ld c,delete
  22.         call bdos
  23.         pop de
  24.         pop hl
  25.         ret
  26.         ENDIF
  27.  
  28. ;
  29. ; Create a new file:
  30. ;
  31. create:
  32.         IF CPM
  33.         ld de,fcb
  34. create2:
  35.         push hl
  36.         push de
  37.         ld hl,12        ;clear extent byte
  38.         add hl,de
  39.         ld (hl),0
  40.         ld c,makfil
  41.         call bdos
  42.         pop de
  43.         ld hl,32
  44.         add hl,de
  45.         ld (hl),0
  46.         pop hl
  47.         cp 255
  48.         ret nz
  49.         ENDIF
  50.  
  51.         jp openo3
  52.  
  53. ;
  54. ; Open a file for output:
  55. ;
  56. openo:  ld de,fcb
  57. openo2: call openg
  58.         ret nz
  59.  
  60. openo3: ld hl,stg3
  61.         jp pstgab
  62.  
  63.         IF CPM
  64. openg:  push hl
  65.         push de
  66.         push de         ;save fcb pointer
  67.         ld c,openfil
  68.         call bdos
  69.         pop de          ;clear nr byte
  70.         ld hl,32
  71.         add hl,de
  72.         ld (hl),0
  73.         cp 0ffh ;return Z set on error
  74.         pop de
  75.         pop hl
  76.         ret
  77.         ENDIF
  78.  
  79.  
  80. ;
  81. ; Close a file:
  82. ;
  83. closef: ld de,fcb
  84. close2:
  85.         IF CPM
  86.         push hl
  87.         ld c,closefil
  88.         call bdos
  89.         pop hl
  90.         cp 255
  91.         ret nz
  92.         ld hl,stg2
  93.         jp pstgab
  94.         ENDIF
  95.  
  96.  
  97. ;
  98. ; Write a sector of a file out to disk:
  99. ;
  100.  
  101.         IF CPM
  102. writs:  ld de,fcb
  103. writs2: push hl
  104.         ld c,wsequen
  105.         call bdos
  106.         pop hl
  107.         or a
  108.         ret z
  109.         ld hl,stg3
  110.         jp pstgab
  111.  
  112. ;
  113. ; Copy 128 bytes from mem at (HL) to tbuff (80h), pad last sector
  114. ; with ^Z's if CPYEND reached and return Cy set if so:
  115. ;
  116.  
  117.  
  118. copys:  ld de,tbuff
  119.         ld b,80h
  120.  
  121. copy1:  ld a,(hl)
  122.         ld (de),a
  123.         push de
  124.         ex de,hl
  125.         lhld cpyend
  126.         ld a,h
  127.         cp d
  128.         jp nz,copy2
  129.         ld a,l
  130.         cp e
  131.         jp z,copy5
  132.  
  133. copy2:  ex de,hl
  134.         pop de
  135.         inc hl
  136.         inc de
  137.         dec b
  138.         jp nz,copy1
  139.         xor a
  140.         ret
  141.  
  142. copy5:  pop de
  143. copy6:  dec b
  144.         jp z,copy7
  145.         ld a,1ah
  146.         ld (de),a
  147.         inc de
  148.         jp copy6
  149.  
  150. copy7:  scf
  151.         ret
  152.         ENDIF           ;end of CP/M-dependent file I/O
  153.  
  154.  
  155. ;
  156. ; Bump line count:
  157. ;
  158.  
  159. bumpnl: push hl
  160.         lhld nlcnt
  161.         inc hl
  162.         shld nlcnt
  163.         pop hl
  164.         ret
  165.  
  166.  
  167. ;
  168. ; print out file name in default fcb:
  169. ;
  170.  
  171. pfnam:  push de
  172.         ld de,fcb
  173.         call pfnam2
  174.         pop de
  175.         ret
  176.  
  177. ;
  178. ; Print out filename of fcb at DE:
  179. ;
  180.  
  181.  
  182. pfnam2: push de
  183.         push hl
  184.         push bc
  185.         ld a,(de)               ;get disk code
  186.         or a
  187.         jp z,pfnm3      ;if file on currently logged disk, don't print
  188.                         ;disk designator.
  189.  
  190. ;       ld c,gdisk      ;This section of code commented out to keep
  191. ;       push de         ;files on the currently logged drive from having
  192. ;       call bdos       ;a disk designator printed before their names.
  193. ;       pop de          ;uncomment the code to put this feature back
  194. ;       inc a           ;into action.
  195.  
  196. pfnm2:  add a,'@'               ;get A = 'A' for drive A, 'B' for B, etc.
  197.         call outch
  198.         ld a,':'
  199.         call outch
  200. pfnm3:  inc de
  201.         ld b,8
  202.         call pnseg
  203.         ld a,(de)
  204.         cp ' '
  205.         ld a,'.'        ;print dot only if filename has extension
  206.         call nz,outch
  207.         ld b,3
  208.         call pnseg
  209.         pop bc
  210.         pop hl
  211.         pop de
  212.         ret
  213.  
  214. pnseg:  ld a,(de)
  215.         cp ' '
  216.         call nz,outch
  217.         inc de
  218.         dec b
  219.         jp nz,pnseg
  220.         ret
  221.  
  222. ;
  223. ; Print out the value in HL in hex, followed by a colon
  224. ; and a space.
  225. ; Upon entry, A non-0: print no leading spaces
  226. ;              A == 0: print leading spaces making total textual output 4 chars
  227. ;
  228. ;
  229.  
  230. prhcs:  push af
  231.         push de
  232.         call prh        ;convert HL to ascii at ascb
  233.         pop de
  234.         pop af
  235.         or a
  236.         ld hl,ascb
  237.         jp z,prhcs3     ;if printing leading spaces, go do it
  238.         dec hl
  239. prhcs1: inc hl
  240.         ld a,(hl)
  241.         cp ' '
  242.         jp z,prhcs1     ;if all four digits, no leading spaces needed
  243.  
  244. prhcs3: call pstg
  245.         ret
  246.  
  247. ;
  248. ; Print A in ASCII followed by a slash
  249. ;
  250.  
  251. prads:  and 1fh         ;max 31
  252.         call pra
  253.         ld a,'/'
  254.         call outch
  255.         ret
  256.  
  257. pra:    cp 10           ;single digit?
  258.         jp nc,pra2      ;if not, go handle double digits
  259. pra0:   add a,'0'               ;print single digit in A
  260. pra1:   call outch
  261.         ret
  262. pra2:   ld b,0          ;calculate 10's digit
  263. pra3:   inc b
  264.         sub 10
  265.         cp 10
  266.         jp nc,pra3
  267.         push af
  268.         ld a,b
  269.         call pra0       ;print tens digit
  270.         pop af
  271.         jp pra0
  272.  
  273. ;
  274. ; Convert value in HL into ASCII at ascb, ascb+1, ascb+2, ascb+3:
  275. ;
  276.  
  277. prh:    push hl
  278.         ld hl,'  '
  279.         shld ascb
  280.         ld hl,' 0'      ;mac doc. is wrong about this!
  281.         shld ascb+2
  282.         pop hl
  283.         inc hl
  284.  
  285. prh0:   ld a,h
  286.         or l
  287.         ret z
  288.         dec hl
  289.         push hl
  290.         ld hl,ascb+3
  291.  
  292. prh1:   ld a,(hl)
  293.         cp ' '
  294.         jp nz,prh2
  295.         ld a,'0'
  296.  
  297. prh2:   inc a
  298.         cp '9'+1
  299.         jp z,prh4
  300.  
  301. prh3:   ld (hl),a
  302.         pop hl
  303.         jp prh0
  304.  
  305. prh4:   ld (hl),'0'
  306.         dec hl
  307.         jp prh1
  308.  
  309.  
  310. ;
  311. ; 2's complement HL:
  312. ;
  313.  
  314. cmh:    push af
  315.         ld a,h
  316.         cpl
  317.         ld h,a
  318.         ld a,l
  319.         cpl
  320.         ld l,a
  321.         inc hl
  322.         pop af
  323.         ret
  324.  
  325.  
  326. ;
  327. ; "Ignore stuff" routine; pass by newlines, white space,
  328. ; module start and end bookkeeping, and keep the lines count
  329. ; (stored in nlcnt) for error reporting:
  330. ;
  331.  
  332. igsht:  ld a,(de)
  333.         cp modbeg       ;begin nested module?
  334.         jp nz,igsh0
  335.  
  336.         inc de
  337.         call pushmn     ;push on modstk, process line number stuff
  338.         jp igsht
  339.  
  340. igsh0:  cp modend
  341.         jp nz,igsh1     ;include file end?
  342.         call popmn      ;restore line number and pop filename off modstk
  343.         jp igsh1a
  344.  
  345. igsh1:  cp 0ffh
  346.         jp nz,igsh2
  347.  
  348. igsh1a: inc de
  349.         jp igsht
  350.  
  351. igsh2:  cp nlcd
  352.         jp nz,igsh3
  353.         call bumpnl
  354.         inc de
  355.         jp igsht
  356.  
  357. igsh3:  or a
  358.         ret
  359.  
  360. ;
  361. ; Push filename at DE onto modstk, save current line number after it,
  362. ; bump modstc, and reset nlcnt:
  363. ;
  364.  
  365. pushmn: push hl         ;save HL
  366.         ld hl,modstc    ;bump modstc
  367.         inc (hl)
  368.         ld a,(hl)
  369.         cp 6
  370.         ld hl,stgine
  371.         call nc,perrab         
  372.  
  373.         lhld modstp     ;get next mod stack entry slot address
  374.         ld b,12
  375.         call ldrc       ;push new module name onto modstk
  376.         push de         ;save text ptr
  377.         ex de,hl
  378.         lhld nlcnt      ;get line count
  379.         ex de,hl                ;line count in DE, modstk ptr in HL
  380.         ld (hl),e
  381.         inc hl
  382.         ld (hl),d
  383.         inc hl
  384.         shld modstp
  385.         ld hl,0
  386.         shld nlcnt      ;clear nlcnt for new module
  387.         pop de          ;restore text pointer
  388.         pop hl          ;restore HL
  389.         ret    
  390.  
  391. ;
  392. ; Pop modstk entry:
  393. ;
  394.  
  395. popmn:  push hl         ;save registers
  396.         push de
  397.         lhld modstp
  398.         dec hl
  399.         ld d,(hl)
  400.         dec hl
  401.         ld e,(hl)               ;DE holds old nlcnt
  402.         ex de,hl
  403.         shld nlcnt      ;restore line count
  404.         ld hl,-12
  405.         add hl,de               ;roll modstk pointer back to start of current level
  406.         shld modstp     ;save modstk pointer
  407.         ld hl,modstc    ;debump module count
  408.         dec (hl)
  409.         pop de
  410.         pop hl
  411.         ret
  412.  
  413. ldrc:   ld a,(de)
  414.         ld (hl),a
  415.         inc hl
  416.         inc de
  417.         dec b
  418.         jp nz,ldrc
  419.         ret
  420.  
  421. ;
  422. ; General purpose ram lde routine.
  423. ; B = byte count
  424. ; C controls direction of lde:
  425. ;       0: DE->HL, 1: HL->DE
  426. ;
  427.  
  428. ldram:  ld a,c
  429.         or a
  430.         jp z,ldr2
  431.         ex de,hl
  432. ldr2:   ld a,(de)
  433.         ld (hl),a
  434.         inc hl
  435.         inc de
  436.         dec b
  437.         jp nz,ldr2
  438.         ld a,c
  439.         or a
  440.         jp z,ldr3
  441.         ex de,hl
  442. ldr3:   push de         ;make sure we don't overflow stack area
  443.         push hl
  444.         lhld coda
  445.         ex de,hl                ;put code area addr in DE
  446.         pop hl          ;and current include stack pointer in HL
  447.         call cmphd
  448.         pop de          ;restore sp
  449.         ret c           ;if OK, return
  450.         ld hl,stgine    ;include error
  451.         jp pstgab       ;print message and quit
  452.  
  453. ;
  454. ; Map alphabetic character in A to upper case:
  455. ;
  456.  
  457. mapuc:  cp 61h
  458.         ret c
  459.         cp 7bh
  460.         ret nc
  461.         sub 20h
  462.         ret
  463.  
  464. ;
  465. ; Special version of mapuc,  which supresses mapping if "mapucv" is true
  466. ;
  467.  
  468. mapuc0: push bc         ;save B
  469.         ld b,a          ;save char to map in B
  470.         lda mapucv      ;get control var
  471.         or a            ;do we do a mapping?
  472.         ld a,b          ;get back char to map in A
  473.         call z,mapuc    ;if we do a mapping, go do it
  474.         pop bc          ;restore B
  475.         ret             ;all done
  476.  
  477.        
  478. ;
  479. ; Print out line number, error message in HL, and set errf so
  480. ; we don't auto-load cc2:
  481. ;
  482.  
  483. perr:   push af
  484.         call pwarn
  485.         ld a,1
  486.         sta errf
  487.         pop af
  488.         ret
  489.  
  490. ;
  491. ; Print out line number, error message in HL, but don't touch
  492. ; errf:
  493. ;
  494.  
  495. pwarn:  push hl
  496.         call pmodnc     ;print module name
  497. perr2:  lhld nlcnt
  498.         call prhcs      ;print line number of error
  499.         pop hl
  500.         call pstg
  501.         ret
  502.  
  503. ;
  504. ; Print module name, colon, space:
  505. ;
  506.  
  507. pmodnc: call pmodnm
  508.         push af
  509.         ld a,':'
  510.         call outch
  511.         ld a,' '
  512.         call outch
  513.         pop af
  514.         ret
  515.  
  516.  
  517. ;
  518. ; Print out module name:
  519. ;
  520.  
  521. pmodnm: push hl
  522.         push de
  523.         lhld modstp
  524.         ld de,-14
  525.         add hl,de
  526.         ex de,hl       
  527.         call pfnam2
  528.         pop de
  529.         pop hl
  530.         ret
  531.  
  532.  
  533. ;
  534. ; Print out string pointed to by HL, with + character shorthand
  535. ; for a CR-LF:
  536. ;
  537.  
  538. pstg:   ld a,(hl)
  539.         or a
  540.         ret z
  541.         cp '+'
  542.         jp z,crlf
  543.         call outch
  544.         inc hl
  545.         jp pstg
  546.  
  547. ;
  548. ; Print strig to console only:
  549. ;
  550.  
  551. pstgco: lda werrs
  552.         push af
  553.         xor a
  554.         sta werrs
  555.         call pstg
  556.         pop af
  557.         sta werrs
  558.         ret
  559.  
  560. ;
  561. ; Output a character of text to the console and/or PROGERRS.$$$ file:
  562. ;
  563.  
  564. outch:  push de
  565.         push bc
  566.         push hl
  567.         push af
  568.  
  569.         if 1==1
  570.         PRCHAR
  571.         else
  572.         ld e,a
  573.         lda werrs
  574.         or a            ;if not writing errs to PROGERRS file,
  575.         jp z,outch3     ;       go write to console
  576.        
  577.         lda nomore      ;if done writing RED errors, just go to console
  578.         or a
  579.         jp nz,outch3
  580.  
  581.         lda errsin
  582.         or a
  583.         jp nz,outch1    ;if RED buffer initialized, go handle I/O
  584.                         ;else initialize RED buffer:
  585.         inc a
  586.         sta errsin
  587.  
  588.         push de
  589.         ld de,redfcb
  590.         lda odisk
  591.         ld (de),a
  592.         call delf2      ;delete previous PROGERRS.$$$
  593.         call create2    ;create new one
  594. ;       call openo2     ;open for output
  595.         ld hl,redbuf
  596.         shld redbp      ;initialize redbuf sector pointer
  597.  
  598.         ld hl,stgeri    ;"RED error output initiated"
  599.         call pstgco     ;print text to console only
  600.         pop de
  601.  
  602. outch1: call redout     ;write char to red output file
  603.  
  604. outch3: ld c,conout
  605.         call bdos
  606.         endif
  607.        
  608.         pop af
  609.         pop hl
  610.         pop bc
  611.         pop de
  612.         ret
  613.  
  614. ; Write a character to RED output buffer, flushing if needed:
  615.  
  616. redout: lhld redbp      ;get redbuf pointer
  617.         ld (hl),e               ;store char
  618.         inc hl          ;bump pointer
  619.         shld redbp      ;save pointer
  620.         ld a,l          ;past end of buffer?
  621.         cp (redbuf+128) and 0ffh
  622.         ret nz          ;if not, return
  623.  
  624.  
  625.  
  626. redwrt: push de
  627.         ld de,redbuf    ;set DMA address to redbuf for sector write
  628.         ld c,sdma
  629.         call bdos
  630.  
  631.         ld de,redfcb
  632.         call writs2     ;write sector
  633.  
  634.         ld de,tbuff     ;set DMA address back for normal file i/o
  635.         ld c,sdma
  636.         call bdos
  637.  
  638.         ld hl,redbuf
  639.         shld redbp     
  640.         pop de
  641.         ret
  642.  
  643.  
  644. ;
  645. ; print "undeclared variable: " and print out the
  646. ; variable name being pointed to by DE:
  647. ;
  648.  
  649. bvarm:  ld hl,stg14
  650. bvarm2: call perr
  651.         push de
  652.         call pvarn      ;print out the name
  653.         pop de
  654.         call crlf
  655.         ret
  656.  
  657. ;
  658. ; print out the variable name pointed to by DE:
  659. ;
  660.  
  661. pvarn:  ld a,(de)
  662.         call varch
  663.         ret c
  664.         call outch
  665.         inc de
  666.         jp pvarn
  667.  
  668. ;
  669. ; Print error message in HL and abort:
  670. ;
  671.  
  672. pstgab:
  673. pstgb2: call pstg
  674.         jp errab
  675.  
  676. ;
  677. ; Print error msg in HL with line number, and abort:
  678. ;
  679.  
  680. perrab: call perr
  681.  
  682. ;
  683. ; Come here to abort, when fatal error has been diagnosed:
  684. ;
  685.  
  686. errab:  lhld errbyt     ;set error byte flag for ZCPR3
  687.         ld (hl),0ffh
  688.  
  689.         call errwrp     ;wrap up any RED file activity
  690.  
  691. errab2: ld a,7          ;ring a bell for errors having occurred
  692.         call outch
  693.         lda erasub      ;bother to erase submit files?
  694.         or a
  695.         jp z,exit
  696.  
  697.         ;ld e,0         ;go to user 0 for submit file erasure
  698.         ;ld c,sguser
  699.  
  700.         IF NOT ALPHA
  701.         ;lda nouser
  702.         ;or a
  703.         ;jp nz,errab3   ;if no user areas, don't do it
  704.  
  705.         ;lda zenvf      ;if not ZSYSTEMS, don't do it
  706.         ;or a
  707.         ;call nz,bdos
  708. ;errab3:
  709.         ENDIF
  710.  
  711.         ld de,subfile   ;erase pending submit files and abort
  712.         call delf2
  713.  
  714. exit:   ;call resetu    ;reset to original user drive/ user area
  715.         QUIT
  716.         ;lda wboote     ;need to perform warm-boot?
  717.         ;or a
  718.         ;jp nz,ram              ;if so, go do it.
  719.         ;lhld spsav     ;get (possibly valid) saved stack pointer
  720.         ;ld sp,hl               ;put into SP
  721.         ;lda ccpok      ;CCP intact?
  722.         ;or a
  723.         ;ret nz         ;if so, return to CCP
  724.         ;jp ram         ;otherwise do a warm boot
  725.  
  726. ;resetu:        ;lda origdsk    ;reset disk and user area to original
  727.         ;ld e,a
  728.         ;ld c,select
  729.         ;call bdos
  730.         ;lda origusr
  731.         ;ld e,a
  732.         ;ld c,sguser
  733.  
  734.         ;IF NOT ALPHA
  735.         ;lda nouser
  736.         ;or a
  737.         ;call z,bdos   
  738.         ;ENDIF
  739.  
  740.         ;ret
  741.  
  742.  
  743.  
  744. ;
  745. ; Print a newline to the console:
  746. ;
  747.  
  748. crlf:   push af
  749.  
  750.         IF CPM
  751.         ld a,cr
  752.         call outch
  753.         ENDIF
  754.  
  755.         ld a,lf
  756.         call outch
  757.         pop af
  758.         ret
  759.  
  760. ;
  761. ; Check for abortion:
  762. ;TODO
  763.  
  764. ckabrt:
  765.         push hl
  766.         push de
  767.         push bc
  768.         push af
  769.  
  770.         ;lda conpol     ;are we polling the console?
  771.         ;or a
  772.         ;jp z,nohit     ;if not, don't do anything
  773.  
  774.         ;ld c,intcon    ;interrogate console status
  775.         ;call bdos
  776.         ;or a
  777.         ;jp z,nohit
  778.         ;ld c,coninp
  779.         ;call bdos      ;if something hit, see if a ^C
  780.         ;cp 3
  781.         ;jp z,intrpt   
  782. nohit:  pop af          ;if not, don't interrupt
  783.         pop bc
  784.         pop de
  785.         pop hl
  786.         ret
  787.  
  788. intrpt: ld hl,stgabo    ; and abort.
  789.         jp pstgab
  790.        
  791. ;
  792. ; Check for stack overflow:
  793. ;
  794.  
  795. chkstk: push hl
  796.         push de
  797.         push bc
  798.         push af
  799.         lhld stkchk
  800.         ld de,0a55ah
  801.         call cmphd      ;make sure stack check word is still intact
  802.         jp z,nohit      ;if so, no problem
  803.         ld hl,stgstk    ;else spew stack overflow message
  804.         jp perrab
  805.  
  806.  
  807. ;
  808. ; Squeeze the symbol table by chopping out the name portion of every entry
  809. ; (reducing the st size by half, since each entry up to now has been
  810. ; 8 chars of name and 8 bytes of attributes):
  811. ;
  812.  
  813. chopst: lhld stno
  814.         ld b,h
  815.         ld c,l          ;BC = symbol entry count
  816.         ld hl,st
  817.         ld de,st
  818.  
  819. sqst2:  ld a,b
  820.         or c
  821.         jp nz,sqst3
  822.         shld stp
  823.         ret
  824.  
  825. sqst3:  push hl
  826.         ld hl,8
  827.         add hl,de
  828.         ex de,hl
  829.         pop hl
  830.  
  831. sqst4:  ld a,(de)
  832.         ld (hl),a
  833.         inc de
  834.         inc hl
  835.         ld a,l
  836.         and 7
  837.         jp nz,sqst4
  838.         dec bc
  839.         jp sqst2
  840.  
  841. ;
  842. ; Write out special CCI-symbol-table file for Kirkland's debugger if "-w"
  843. ; option given...write out stno entries from symbol table at st, each
  844. ; 16 bytes long. Call the file <name>.CDB ... this is gonna be a neat hack!
  845. ;
  846.  
  847. wst4db: lda kflg        ;was -w even given?
  848.         or a            ;if not, return
  849.         ret z
  850.  
  851.         ld hl,st        ;get size of symbol table in HL
  852.         call cmh
  853.         ex de,hl
  854.         lhld stp        ;get symbol table next free slot pointer
  855.         shld cpyend     ;this is where we'll stop writing to the output file.
  856.         add hl,de
  857.         shld st-2       ;put symbol table size in place
  858.  
  859.         IF CPM
  860.         ld hl,fcb+9
  861.         ld (hl),'C'
  862.         inc hl
  863.         ld (hl),'D'
  864.         inc hl
  865.         ld (hl),'B'
  866.         lda odisk       ;set output disk designation
  867.         sta fcb
  868.         call delfil     ;delete old versions
  869.         call create     ;create output file
  870. ;       call openo      ;and open it for output
  871.  
  872.         ld hl,st-2
  873. wstdb2: call copys
  874.         push af
  875.         call writs
  876.         pop af
  877.         jp nc,wstdb2
  878.         call closef     ;close the output file.
  879.         ENDIF
  880.  
  881.         ret
  882.  
  883.  
  884. ;
  885. ; Little general purpose utility to compare HL and DE,
  886. ; and return C set if HL < DE
  887. ;
  888.  
  889. cmphd:  ld a,h
  890.         cp d
  891.         ret nz
  892.         ld a,l
  893.         cp e
  894.         ret
  895.  
  896.  
  897. ;
  898. ; Routine to make sure we haven't overflowed available memory space. At
  899. ; first, we try to use memory below the command processor (under both
  900. ; CP/M and MARC). If we run out of room, we either punt the CCP under
  901. ; CP/M or do the maxmem call under MARC to get more memory.
  902. ;
  903.  
  904. ckov:   push hl
  905.         push de
  906. ckov0:  lda curtop+1    ;high order byte of top of mem addr
  907.         dec a
  908.         ld d,a
  909.         ld a,h
  910.         cp d
  911.         jp c,ckovok     ;overflow?
  912.  
  913.         IF CPM
  914.         lda ccpok       ;under CP/M, is the CCP still intact?
  915.         or a
  916.         jp nz,ckov1     ;if so, go try for more memory
  917.         ENDIF
  918.  
  919.         ld hl,stgov     ;We've used all we can...it's all over now.
  920.         jp pstgab
  921.  
  922. ckov1:
  923.         IF CPM
  924.         push hl
  925.         ld hl,NEDOOSMEMTOP;lhld bdosp   ;change curtop to reflect BDOS address now
  926.         ld l,0          ;zero out low order byte
  927.         shld curtop
  928.         pop hl
  929.         xor a           ;and tell that the CCP is now defunct
  930.         sta ccpok
  931.         jp ckov0
  932.         ENDIF  
  933.  
  934.  
  935. ckovok: pop de
  936.         pop hl
  937.         ret
  938.  
  939.  
  940.  
  941. ;
  942. ; The following function is hairy. It forms the core hack of the BDS C
  943. ; parsing algorithm: it ldes expands and compacts text at the current
  944. ; text pointer location (DE), where A upon entry is negative to EXPAND
  945. ; by -(A), positive to squeeze by A, or zero to do nothing.
  946. ;
  947. ; This is getting documented approximately 3 1/2 years after being written.
  948. ; It's been one HELL of a WIERD three and a half years!!!!!!!!!!
  949. ;
  950.  
  951. TESTM:  EQU 0
  952.  
  953.  
  954. mvtxt:  or a            ;check for zero
  955.         ret z           ;return if so
  956.         jp p,sqish      ;if positive, go squish
  957.  
  958.         cpl             ;otherwise negate
  959.         inc a
  960.  
  961.         push hl         ;save registers
  962.         push bc
  963.         push de
  964.         push af
  965.  
  966.         ld a,(de)
  967.         cp 0ffh
  968.         jp nz,mvtxt1
  969.  
  970.         pop af
  971.         cp 1
  972.         jp nz,mvtxt0
  973.         pop de
  974.         pop bc
  975.         pop hl
  976.         ret
  977.  
  978. mvtxt0: pop de
  979.         pop bc
  980.         pop hl
  981.         inc de
  982.         dec a
  983.         cpl
  984.         inc a
  985.         call mvtxt
  986.         dec de
  987.         ret
  988.  
  989.         IF TESTM
  990.  
  991.         call tstriv     ;see if expansion is all into filler bytes...
  992.         jp nz,mvtxt1    ;if not, go do standard expansion
  993.  
  994.         pop af          ;if so, we don't need to do anything,
  995.         pop de          ;so pop registers and return.
  996.         pop bc
  997.         pop hl
  998.         ret
  999.  
  1000. ;
  1001. ; Returns Z set if there are at least (A) FF bytes at (DE).
  1002. ; Preserves DE but not necessarily A:
  1003. ;
  1004.  
  1005. tstriv: push de         ;save text pointer
  1006. tstrv2: ld a,(de)               ;text for FF
  1007.         cp 0FFh
  1008.         jp nz,tstrv3    ;if not, trivial test fails.
  1009.         inc de          ;else bump text pointer to next char
  1010.         dec a           ;and test for completion
  1011.         jp nz,tstrv2    ;if haven't found enough, go on looking
  1012.                         ;otherwise we found enough--success!
  1013. tstrv3: pop de
  1014.         ret
  1015.         ENDIF
  1016.  
  1017.  
  1018. mvtxt1: pop af
  1019.         sta mvtmp
  1020.         jp fndff
  1021.  
  1022. mvtxt2: lda mvtmp
  1023.         ld h,d
  1024.         ld l,e
  1025.         dec de
  1026.  
  1027. mvtxt3: push af
  1028.         ld a,(de)
  1029.         ld (hl),a
  1030.         pop af
  1031.         pop bc
  1032.         push af
  1033.         ld a,c
  1034.         cp e
  1035.         jp nz,mvtxt5
  1036.         ld a,b
  1037.         cp d
  1038.         jp nz,mvtxt5
  1039.         pop af
  1040.         dec a
  1041.         jp nz,mvtxt6
  1042.         pop bc
  1043.         pop hl
  1044.         ret
  1045.  
  1046. mvtxt5: pop af
  1047.         push bc
  1048.         dec hl
  1049.  
  1050. mvtxt6: dec de
  1051.         jp mvtxt3
  1052.  
  1053.  
  1054. fndff:  ld c,a
  1055.         sta fndtmp
  1056.         ld b,7
  1057.         ld a,(de)
  1058.         or a
  1059.         jp nz,fff0
  1060.         ld a,1
  1061.         call expnd
  1062.         inc de
  1063.  
  1064. fff0:   ld a,(de)
  1065.         or a
  1066.         jp z,fff2
  1067.         cp 0ffh
  1068.         jp nz,fff1
  1069. fff0b:  inc de
  1070.         ld a,(de)
  1071.         cp 0ffh
  1072.         dec de 
  1073.         ld a,(de)
  1074.         jp nz,fff1
  1075.         dec c
  1076.         jp z,mvtxt2
  1077.  
  1078.         ld b,7
  1079.         push de
  1080. fff0a:  inc de
  1081.         jp fff0
  1082.  
  1083. fff1:   cp nlcd
  1084.         jp z,fff1a
  1085.         cp cr
  1086.         jp nz,fff4
  1087. fff1a:  dec de
  1088.         cp '\'
  1089.         inc de
  1090.         jp z,fff4
  1091.         dec de
  1092.         dec de
  1093.         ld a,(de)
  1094.         inc de
  1095.         inc de
  1096.         cp '\'
  1097.         jp z,fff4
  1098.         dec b
  1099.         jp nz,fff0a
  1100.         ld b,7
  1101.         inc de
  1102.         ld a,(de)
  1103.         cp 0ffh
  1104.         jp z,fff0b
  1105.  
  1106. fff2:   ld a,c
  1107.         add a,40
  1108.         call expnd
  1109.  
  1110. fff3:   dec c
  1111.         jp z,mvtxt2
  1112.         push de
  1113.         inc de
  1114.         jp fff3
  1115.  
  1116. fff4:   ld a,(de)
  1117.         cp swtbc
  1118.         jp nz,fff5
  1119.         inc de
  1120.         ld a,(de)
  1121.         ld l,a
  1122.         ld h,0
  1123.         add hl,hl
  1124.         add hl,hl
  1125.         inc hl
  1126.         inc hl
  1127.         inc de
  1128.         add hl,de
  1129.         ex de,hl
  1130.         jp fff0
  1131.  
  1132. fff5:   call cdtst
  1133.         jp c,fff6
  1134.         inc de
  1135.         inc de
  1136.         jp fff0a
  1137.  
  1138. fff6:   cp modbeg
  1139.         jp nz,fff0a
  1140.         ld hl,14
  1141.         add hl,de
  1142.         ex de,hl
  1143.         jp fff0
  1144.  
  1145. sqish:  push bc
  1146.         ld b,a
  1147.         ld a,0ffh
  1148. sqish2: ld (de),a
  1149.         inc de
  1150.         dec b
  1151.         jp nz,sqish2
  1152.         pop bc
  1153.         ret
  1154.  
  1155.  
  1156. expnd:  push hl
  1157.         push bc
  1158.         push af
  1159.         push de
  1160.         lhld eofad
  1161.         ld b,h
  1162.         ld c,l
  1163.         ld e,a
  1164.         ld d,0
  1165.         add hl,de
  1166.         push hl
  1167.         push bc
  1168.         shld eofad
  1169.         ld b,h
  1170.         ld c,l
  1171.         lhld meofad
  1172.         call max
  1173.         shld meofad
  1174.         pop bc
  1175.         pop hl
  1176.         call ckov
  1177.         pop de
  1178.  
  1179. expnd1: call mvbhd
  1180.         pop af
  1181.         ld b,a
  1182.         push de
  1183. expnd4: ld a,0ffh
  1184.         ld (de),a
  1185.         inc de
  1186.         dec b
  1187.         jp nz,expnd4
  1188.         pop de
  1189.         pop bc
  1190.         pop hl
  1191.         ret
  1192.  
  1193.  
  1194. ;
  1195. ; Routine to lde stuff from (BC) to (HL), decrementing both
  1196. ; as we go, until BC passes DE -- doing it by block lde if possible
  1197. ; (if runnign a Z80), or by brute force if on an 8080 or 8085.
  1198. ; Clobbers BC and HL.
  1199. ;
  1200.  
  1201. mvbhd:  lda z80f        ;z80?
  1202.         or a
  1203.         jp z,mvbhdl     ;if not, do it the long way
  1204.  
  1205.         push de
  1206.         push hl
  1207.         ex de,hl
  1208.         call cmh
  1209.         add hl,bc
  1210.         inc hl
  1211.         push hl
  1212.         ld h,b
  1213.         ld l,c
  1214.         pop bc
  1215.         pop de
  1216.         db 0edh,0b8h    ;ldir instuction
  1217.         pop de
  1218.         ret
  1219.  
  1220.  
  1221. mvbhdl: ld a,(bc)               ;do it the long way
  1222.         ld (hl),a
  1223.         ld a,c
  1224.         cp e
  1225.         jp nz,mvbhd2
  1226.         ld a,b
  1227.         cp d
  1228.         ret z
  1229. mvbhd2: dec hl
  1230.         dec bc
  1231.         jp mvbhd
  1232.  
  1233.  
  1234. ;
  1235. ; Return Cy true if byte in A is a code byte:
  1236. ;
  1237.  
  1238. cdtst:  cp concd
  1239.         ret c
  1240.         cp strcd+1
  1241.         ccf
  1242.         ret
  1243.  
  1244. ;
  1245. ; Purge FF's and related garbage/filler bytes from text:
  1246. ;
  1247.  
  1248. fixt:   lhld coda       ;HL is source pointer
  1249.         ld d,h          ;DE is dest pointer
  1250.         ld e,l
  1251.  
  1252. fix0:   ld a,(hl)               ;end of code?
  1253.         or a
  1254.         jp nz,fix2
  1255.  
  1256.         ld (de),a               ;yes. handle strings.
  1257.         inc de
  1258.         inc hl
  1259. fix1:   ld a,(hl)
  1260.         cp 1ah          ;end of strings?
  1261.         jp nz,fix1a     ;if not, still doing strings.
  1262.         ld (de),a               ;yes.
  1263.         ex de,hl
  1264.         shld eofad
  1265.         ret
  1266.  
  1267. fix1a:  ld b,3          ;handle string storge.
  1268.         call ldb
  1269.         ld b,a
  1270.         call ldb
  1271.         jp fix1
  1272.  
  1273. fix2:   call cdtst      ;three byte code?
  1274.         jp c,fix4
  1275.         ld b,3
  1276.         call ldb
  1277.         jp fix0
  1278.  
  1279. fix4:   cp 0ffh ;garbage byte?
  1280.         jp nz,fix5
  1281.         inc hl          ;yes. skip it.
  1282.         jp fix0
  1283.  
  1284. fix5:   cp swtbc        ;switch statement?
  1285.         jp nz,fix8
  1286.  
  1287.         ld (de),a               ;yes.
  1288.         inc de
  1289.         inc hl
  1290. fix6:   ld a,(hl)
  1291.         cp 0ffh
  1292.         jp nz,fix7
  1293.         inc hl
  1294.         jp fix6
  1295. fix7:   push hl
  1296.         ld l,a
  1297.         ld h,0
  1298.         add hl,hl
  1299.         add hl,hl
  1300.         inc hl
  1301.         inc hl
  1302.         inc hl
  1303.         ld b,h
  1304.         ld c,l
  1305.         pop hl
  1306.         call mvmd
  1307.         jp fix0
  1308.  
  1309. fix8:   cp modbeg       ;start of module?
  1310.         jp nz,fix10
  1311.         ld b,12 ;yes. copy module name
  1312.         call ldb
  1313.         jp fix0
  1314.  
  1315. fix10:  ld (de),a
  1316.         inc hl
  1317.         inc de
  1318.         jp fix0
  1319.  
  1320.  
  1321. fix11:  ld hl,oshit
  1322.         call pstgab
  1323.  
  1324. ldb:    inc b
  1325. ldb2:   dec b
  1326.         ret z
  1327.         ld a,(hl)
  1328.         ld (de),a
  1329.         inc hl
  1330.         inc de
  1331.         jp ldb2
  1332.  
  1333.  
  1334.  
  1335. mvmd:   lda z80f
  1336.         or a
  1337.         jp z,mvmdl      ;if on 8080, can't use block lde
  1338.         db 0edh,0b0h    ;else can
  1339.         ret
  1340.  
  1341. mvmdl:  ld a,(hl)               ;do it the hard way for 8080
  1342.         ld (de),a
  1343.         inc hl
  1344.         inc de
  1345.         dec bc
  1346.         ld a,b
  1347.         or c
  1348.         jp nz,mvmd
  1349.         ret
  1350.  
  1351.  
  1352. pascd:  call igsht
  1353.         ret z
  1354.         call cdtst
  1355.         jp nc,pscd2
  1356.         xor a
  1357.         inc a
  1358.         ld a,(de)
  1359.         ret
  1360.  
  1361. pscd2:  inc de
  1362.         inc de
  1363.         inc de
  1364.         jp pascd
  1365.  
  1366.  
  1367. fsemi:  ld a,semi
  1368.  
  1369.  
  1370. ;
  1371. ; Find next occurence of the character passed in A:
  1372. ;
  1373.  
  1374. findc:  ld b,a
  1375. findc1: ld a,(de)
  1376.         cp b
  1377.         ret z
  1378.         or a
  1379.         jp nz,finc2
  1380.         ld hl,stg10
  1381.         jp fatal
  1382.  
  1383. finc2:  cp nlcd
  1384.         jp nz,finc3
  1385.         call bumpnl
  1386.  
  1387. finc3:  inc de
  1388.         call cdtst
  1389.         jp c,finc4
  1390.         inc de
  1391.         inc de
  1392.         jp findc1
  1393.  
  1394. finc4:  push af
  1395.         lda eradf
  1396.         or a
  1397.         jp nz,finc5
  1398.         pop af
  1399.         jp findc1
  1400.  
  1401. finc5:  pop af
  1402.         cp 80h
  1403.         jp c,findc1     ;if no control keyword found, no problem
  1404.         cp 9dh
  1405.         jp nc,findc1
  1406.  
  1407.         cp 8fh          ;special case of a keyword allowed in
  1408.         jp z,findc1     ;an expression: sizeof
  1409.  
  1410.         lhld nlcnt      ;else error...probably missing semicolon
  1411.         push hl
  1412.         lhld errad
  1413.         shld nlcnt
  1414.         ld hl,stg25
  1415.         call perr
  1416.         pop hl
  1417.         shld nlcnt
  1418.         dec de
  1419.         dec de
  1420.         ld a,semi
  1421.         ld (de),a
  1422.         ret
  1423.  
  1424. ;
  1425. ; New routine that expects to see a semicolon as
  1426. ; the first non-trivial item in text; else error given.
  1427. ;
  1428.  
  1429. esemi:  call igsht
  1430.         cp semi ;next thing a semi?
  1431.         ret z           ;if so, OK-- else insert one.
  1432.  
  1433. insrts: lhld nlcnt      ;save real line count
  1434.         push hl
  1435.         lhld esadr      ;get fake count
  1436.         shld nlcnt
  1437.         ld hl,stg25
  1438.         call perr       ;print error
  1439.         pop hl
  1440.         shld nlcnt
  1441.         ld a,negone     ;make room for automatic semi
  1442.         call mvtxt
  1443.         ld a,semi       ;just to aid diagnosing later errors
  1444.         ld (de),a
  1445.         ret
  1446.  
  1447.  
  1448. tstty:  cp chrcd
  1449.         ret c
  1450.         cp gotcd
  1451.         ccf
  1452.         ret
  1453.  
  1454.  
  1455. ;
  1456. ; Return Cy false if character in A is legal anywhere in an identifier name:
  1457. ;
  1458.  
  1459. varch:  call varch2
  1460.         ret nc
  1461.         cp '0'
  1462.         ret c
  1463.         cp '9'+1
  1464.         ccf
  1465.         ret
  1466.  
  1467. ;
  1468. ; Return Cy false if char in A is legal as FIRST char in an identifier name:
  1469. ;
  1470.  
  1471. varch2: cp 'A'
  1472.         ret c
  1473.         cp 'Z'+1
  1474.         ccf
  1475.         ret nc
  1476.         cp 5fh
  1477.         ret z
  1478.         cp 61h
  1479.         ret c
  1480.         cp 7bh
  1481.         ccf
  1482.         ret
  1483.  
  1484.  
  1485. ;
  1486. ; Advance text pointer past identifier at DE:
  1487. ;
  1488.  
  1489. pasvr:  call igsht
  1490. psvr2:  call varch
  1491.         jp nc,psvr3
  1492.         call igsht
  1493.         ret
  1494.  
  1495. psvr3:  inc de
  1496.         ld a,(de)
  1497.         jp psvr2
  1498.  
  1499.  
  1500. ;
  1501. ; Advance text pointer past parentheses at DE:
  1502.  
  1503. mtchp:  push hl
  1504.         call mtchp1
  1505.         pop hl
  1506.         ret
  1507.  
  1508. mtchp1: call igsht
  1509.         cp open
  1510.         jp z,mtchq
  1511.         ld hl,stg40
  1512.         call perr
  1513.         call fsemi
  1514.         ret
  1515.  
  1516. mtchq:  lhld nlcnt
  1517.         shld mtpln
  1518.  
  1519. mtchpa: inc de
  1520. mtchpb: call pascd
  1521.         jp nz,mtchpc
  1522. mtchpe: lhld mtpln
  1523.         shld nlcnt
  1524.         ld hl,stgbp
  1525.         jp fatal
  1526.  
  1527. mtchpc: cp close
  1528.         jp nz,mtp2
  1529.         push hl         ;save line count for error diagnostics
  1530.         lhld nlcnt
  1531.         shld esadr
  1532.         pop hl
  1533.         inc de
  1534.         call igsht
  1535.         ret
  1536.  
  1537. mtp2:   cp semi ;allow semicolons in parentheses only
  1538.         jp nz,mtp3      ;if semiok is non-zero.
  1539.         lda semiok
  1540.         or a
  1541.         jp z,mtchpe
  1542.         jp mtchpa
  1543.  
  1544. mtp3:   cp open
  1545.         jp nz,mtchpa
  1546.         call mtchpa
  1547.         jp mtchpb
  1548.  
  1549. ;
  1550. ; Install identifier at DE in symbol table position given in HL:
  1551. ;
  1552.  
  1553. instt:  push de
  1554.         push de
  1555.         lhld stp
  1556.         push hl
  1557.         ld de,16
  1558.         add hl,de
  1559.         lda coda+1
  1560.         ld b,a
  1561.         ld a,h
  1562.         cp b
  1563.         jp c,instta
  1564. instt0: ld hl,stgom
  1565.         lda preflag
  1566.         or a
  1567.         jp z,fatal
  1568.         jp pstgab
  1569.  
  1570. instta: pop hl
  1571.         pop de
  1572.         ld c,0
  1573. inst2:  ld a,(de)
  1574.         ld (hl),a
  1575.         inc c
  1576.         inc hl
  1577.         inc de
  1578.         ld a,(de)
  1579.         call varch
  1580.         jp c,inst4
  1581.         ld a,c
  1582.         cp 8
  1583.         jp c,inst2
  1584.  
  1585. inst3:  inc de
  1586.         inc c
  1587.         ld a,(de)
  1588.         call varch
  1589.         jp nc,inst3
  1590.  
  1591. inst4:  dec hl
  1592.         ld a,(hl)
  1593.         or 80h
  1594.         ld (hl),a
  1595.         inc hl
  1596.         ld a,8
  1597.         sub c
  1598.         ld e,a
  1599.         ld d,0
  1600.         jp c,inst5
  1601.         add hl,de
  1602. inst5:  shld tempd
  1603.         pop de
  1604.         ret
  1605.  
  1606.  
  1607.  
  1608. cvtst:  push de
  1609.         add hl,hl
  1610.         add hl,hl
  1611.         add hl,hl
  1612.         add hl,hl
  1613.         ex de,hl
  1614.         ld hl,st
  1615.         add hl,de
  1616.         ld de,8
  1617.         add hl,de
  1618.         pop de
  1619.         ld a,(hl)
  1620.         ret
  1621.  
  1622. finds:  lda clev
  1623.         sta flev
  1624.         call fs
  1625.         ret nc
  1626.         xor a
  1627.         sta flev
  1628.  
  1629.  
  1630. fs:     lhld stno
  1631.         ld b,h
  1632.         ld c,l
  1633.         ld hl,st
  1634.  
  1635. fs2:    ld a,b
  1636.         or c
  1637.         jp nz,fs3
  1638.         scf
  1639.         ret
  1640.  
  1641. fs3:    push de
  1642.         push bc
  1643.         call idcmp
  1644.         jp z,fs4
  1645.         ld de,16
  1646. fs3a:   add hl,de
  1647.         pop bc
  1648.         pop de
  1649.         dec bc
  1650.         jp fs2
  1651.  
  1652. fs4:    dec hl
  1653.         ld a,l
  1654.         and 0f8h
  1655.         ld l,a
  1656.         ld de,9
  1657.         add hl,de
  1658.         shld inadsv
  1659.         ld a,(hl)
  1660.         and 3fh
  1661.         ld d,a
  1662.         lda flev
  1663.         cp d
  1664.         jp z,fs5
  1665.         ld de,7
  1666.         jp fs3a
  1667.  
  1668. fs5:    pop hl
  1669.         call cmh
  1670.         ex de,hl
  1671.         lhld stno
  1672.         add hl,de
  1673.         pop de
  1674.         xor a
  1675.         ret
  1676.  
  1677. initst: lhld stsiz
  1678.         ld b,h
  1679.         ld c,l
  1680.         ld hl,st
  1681. inits1: ld (hl),0
  1682.         inc hl
  1683.         dec bc
  1684.         ld a,b
  1685.         or c   
  1686.         jp nz,inits1
  1687.         ret
  1688.  
  1689. ;
  1690. ; compare the symbol table entry at HL with the text identifier
  1691. ; at DE:
  1692. ;
  1693.  
  1694. idcmp:  push de
  1695.         push hl
  1696.         ld c,1          ;initialize char count
  1697. idcmp2: ld a,(hl)
  1698.         and 7fh         ;strip end-of-text bit from char of st entry
  1699.         ld b,a          ;put it in B.
  1700.         ld a,(de)               ;get a character from text.
  1701.         cp b            ;same?
  1702.         jp z,idcmp3     ;if so, go check rest of identifier
  1703. idcp2a: pop hl          ;else no match.
  1704.         pop de
  1705.         xor a           ;clear zero flag
  1706.         inc a           ;by incrementing from zero,
  1707.         scf             ;and also set the carry flag.
  1708.         ret
  1709.  
  1710. idcmp3: ld a,(hl)               ;ok, so far it matches.
  1711.         or a            ;was it the last char of the st entry?
  1712.         inc hl
  1713.         jp m,idcmp4     ;jump if it was
  1714.         inc de          ;it wasn't. bump text pointer, char count,
  1715.         inc c
  1716.         jp idcmp2       ;and go look at next charcter
  1717.  
  1718. idcmp4: ld a,c          ;end of symbol. if we've already seen 8 characters,
  1719.         cp 8            ;ignore rest of symbol at DE (insignificant chars)
  1720.         jp z,idcmp5    
  1721.         inc de          ;haven't seen 8 chars yet...is next char of text
  1722.         ld a,(de)               ;a legal identifier character?
  1723.         call varch
  1724.         jp nc,idcp2a    ;if so, no match.
  1725.  
  1726. idcp4a: xor a           ;we have a match. set Z.
  1727.         pop de
  1728.         pop de
  1729.         ret
  1730.  
  1731. idcmp5: inc de          ;come here to pass over superfluous chars of text
  1732.         ld a,(de)
  1733.         call varch
  1734.         jp c,idcp4a
  1735.         inc c           ;making sure to bump the char count in C as we go.
  1736.         jp idcmp5
  1737.  
  1738.  
  1739. ;
  1740. ; Make function name table:
  1741. ;
  1742.  
  1743. mkfnt:  lhld stp
  1744.         shld fnts
  1745.         shld fntp
  1746.         lhld stno
  1747.         ld b,h
  1748.         ld c,l
  1749.         ld hl,st+8
  1750.  
  1751. mkft1:  ld a,b
  1752.         or c
  1753.         jp nz,mkft2     ;done?
  1754.         lhld fntp       ;yes. make sure we haven't overflowed  
  1755.         ex de,hl                ;the symbol table
  1756.         lhld coda
  1757.         call cmphd      ;return C if code area < end of func name table
  1758.         ret nc
  1759.         ld hl,stgom     ;list too long. complain and abort
  1760.         jp pstgab
  1761.  
  1762. mkft2:  ld a,(hl)
  1763.         rra
  1764.         push hl
  1765.         push bc
  1766.         call c,mkft3
  1767.         pop bc
  1768.         pop hl
  1769.         ld de,16
  1770.         add hl,de
  1771.         dec bc
  1772.         jp mkft1
  1773.  
  1774. mkft3:  ld de,-8
  1775.         add hl,de
  1776.         push hl
  1777.         ld h,b
  1778.         ld l,c
  1779.         call cmh
  1780.         ex de,hl
  1781.         lhld stno
  1782.         add hl,de
  1783.         ex de,hl
  1784.         lhld fntp
  1785.         ld (hl),e
  1786.         inc hl
  1787.         ld (hl),d
  1788.         inc hl
  1789.         pop de
  1790.  
  1791. mkft4:  ld a,(de)
  1792.         ld (hl),a
  1793.         inc de
  1794.         inc hl
  1795.         or a
  1796.         jp p,mkft4
  1797.         shld fntp
  1798.         ret
  1799.  
  1800. mvfnt:  lhld fnts
  1801.         call cmh
  1802.         ex de,hl
  1803.         lhld fntp
  1804.         add hl,de
  1805.         shld st-2
  1806.         ld b,h
  1807.         ld c,l
  1808.         lhld fnts
  1809.         ex de,hl
  1810.         lhld stp
  1811.  
  1812. mvft1:  ld a,b
  1813.         or c
  1814.         jp z,mvft2
  1815.         ld a,(de)
  1816.         ld (hl),a
  1817.         inc hl
  1818.         inc de
  1819.         dec bc
  1820.         jp mvft1
  1821.  
  1822. mvft2:  shld fntp
  1823.         ret
  1824.  
  1825. ;
  1826. ; Perform "big expansion" of text:
  1827. ;
  1828.  
  1829. bexp:   ex de,hl
  1830.         call cmh
  1831.         ld b,h
  1832.         ld c,l
  1833.         lhld eofad
  1834.         push hl
  1835.         push hl
  1836.         add hl,bc
  1837.         ld b,h
  1838.         ld c,l
  1839.         pop hl
  1840.         inc bc
  1841.         add hl,de
  1842.         shld eofad
  1843.         call ckov
  1844.         pop de
  1845.  
  1846. bexp1:  ld a,b
  1847.         or c
  1848.         jp z,bexp2
  1849.         ld a,(de)
  1850.         ld (hl),a
  1851.         dec hl
  1852.         dec bc
  1853.         dec de
  1854.         jp bexp1
  1855.  
  1856. bexp2:  inc de
  1857.         ret
  1858.  
  1859. ;
  1860. ; Either write CCI file to disk (if -az given, CP/M only) or auto-load
  1861. ; into CC2:
  1862. ;
  1863.  
  1864. writf:  lhld extsa      ;put externals size word in place
  1865.         shld st-6
  1866.  
  1867.         ld hl,st        ;get size of symbol table in HL
  1868.         call cmh
  1869.         ex de,hl
  1870.         lhld stp
  1871.         add hl,de
  1872.         shld st-4       ;put symbol table size in place
  1873.  
  1874.         lhld eofad      ;now copy tokenized code down to just past the
  1875.         ld b,h          ;end of the symbol table
  1876.         ld c,l
  1877.         lhld coda
  1878.         ex de,hl
  1879.         lhld fntp
  1880.                
  1881. writ1:  ld a,(de)
  1882.         ld (hl),a
  1883.         inc hl
  1884.         inc de
  1885.         ld a,e
  1886.         cp c
  1887.         jp nz,writ1
  1888.         ld a,d
  1889.         cp b
  1890.         jp nz,writ1
  1891.         shld eofad
  1892.  
  1893.         IF CPM
  1894.         lda chainf
  1895.         or a
  1896.         jp nz,chain
  1897.         ENDIF
  1898.  
  1899.         IF NOT CPM
  1900.         jp chain
  1901.         ENDIF
  1902.  
  1903.         IF CPM
  1904. writ1a: ld hl,fcb+9
  1905.         ld (hl),'C'
  1906.         inc hl
  1907.         ld (hl),'C'
  1908.         inc hl
  1909.         ld (hl),'I'
  1910.         lda odisk       ;set output disk designation
  1911.         sta fcb
  1912.         call delfil
  1913.         call create     ;create output file
  1914.         lhld eofad      ;copy till end of all data
  1915.         shld cpyend
  1916.  
  1917.         ld hl,st-6
  1918. writ2:  call copys
  1919.         push af
  1920.         call writs
  1921.         pop af
  1922.         jp nc,writ2
  1923.         call closef     ;close the output file.
  1924.         ret
  1925.         ENDIF
  1926.  
  1927.  
  1928. chain:
  1929.         lda cc2dsk      ;get default cc2 disk
  1930.         sta cfcb        ;set as first byte of fcb
  1931.  
  1932.         IF NOT ALPHA
  1933.         ;lda nouser     ;don't futz with user areas?
  1934.         ;or a
  1935.         ;jp nz,chain0   ;if not, skip chandng user area
  1936.  
  1937.         ;lda cc2usr     ;get cc2 default user area
  1938.         ;ld e,a
  1939.  
  1940.         ;ld c,sguser
  1941.         ;call bdos      ;change to that user area
  1942.         ENDIF
  1943.  
  1944. chain0: call occ2       ;try to open in default user area and disk
  1945.  
  1946.         ;push af        ;save condition
  1947.         ;lda curdsk     ;switch back to current disk and user area
  1948.         ;inc a
  1949.         ;sta cfcb
  1950.  
  1951.         ;IF NOT ALPHA
  1952.         ;lda nouser
  1953.         ;or a
  1954.         ;jp nz,chain1
  1955.  
  1956.         ;lda curusr     ;change back to current user area
  1957.         ;ld e,a
  1958.  
  1959.         ;ld c,sguser
  1960.         ;call bdos
  1961.         ;ENDIF
  1962.  
  1963. ;chain1:        pop af          ;get back condition of first cc2 open attempt
  1964.         jp nz,ch3               ;go read in if prior open succeeded
  1965.  
  1966.         call occ2       ;else try to read in current disk and user area...
  1967.         jp nz,ch3               ;if ok, go read
  1968.  
  1969.         jp cc2bad       ;else give up
  1970.  
  1971. occ2:   lhld curtop
  1972.         push hl         ;try to open cc2
  1973.         ld de,-33
  1974.         add hl,de
  1975.         push hl
  1976.         ld de,cfcb
  1977.         ld b,16
  1978. ch2:    ld a,(de)
  1979.         ld (hl),a
  1980.         inc hl 
  1981.         inc de
  1982.         dec b
  1983.         jp nz,ch2
  1984.         pop de
  1985.         ld c,openfil
  1986.         call bdos       ;try to open cc2.com
  1987.         pop hl
  1988.         dec hl
  1989.         ld (hl),0               ;clear nr field of CC2 fcb
  1990.         cp 255          ;cc2 on disk?
  1991.         ret
  1992.  
  1993. cc2bad: ld hl,stgcce    ;nope. complain and write out cci file
  1994.  
  1995.         call pstg
  1996.         jp writ1a
  1997.  
  1998. ch3:   
  1999.         call ldef       ;lde schlameel to high ram
  2000.         ld hl,tbuff     ;lde bootstrap to tbuff (== just 80h under MARC)
  2001.         ld de,bootcode
  2002.         ld b,bootlen
  2003. ch4:    ld a,(de)
  2004.         ld (hl),a
  2005.         inc hl
  2006.         inc de
  2007.         dec b
  2008.         jp nz,ch4
  2009.  
  2010. ;
  2011. ; Now set up stack at ram area, and push all data that will have to
  2012. ; be popped back into cc2. The order of pushing, and resulting address
  2013. ; in cc2, are as follows:
  2014. ;
  2015. ;       no.     item    address in cc2
  2016. ;       ---     ----    --------------
  2017. ;       0       kflg    110h
  2018. ;       1       odisk   5fh             (CP/M only)
  2019. ;       2       optimf  104h
  2020. ;       3       loadad  105h-106h
  2021. ;       4       eflag   109h
  2022. ;       5       exaddr  107h-108h
  2023. ;       6       curtop  10ch-10dh
  2024. ;       7       ccpok   10eh            (ccpok: b0, oktort: b1, wboote b2,
  2025. ;                                               zenvf: b3)
  2026. ;               maxmd   10eh            (MARC only)
  2027. ;       8       spsav   10ah-10bh       (CP/M only)
  2028. ;               fnam    10ah-10bh       (MARC only)
  2029. ;       9       erasub  10fh            (CP/M only)
  2030. ;       10      defsub/ 111h-112h       (CP/M only)
  2031. ;               conpol
  2032. ;       11      errbyt  113h-114h       (CP/M only)
  2033. ;      
  2034. ; The bootstrap pops these in the reverse order, or course, and sets
  2035. ; them up in the newly-loaded in cc2.com file.
  2036. ;
  2037.  
  2038.         ld sp,tpa
  2039.         lda kflg        ;save CDB flag
  2040.         push af
  2041.         lda odisk       ;save output disk flag
  2042.         push af
  2043.         lda optim       ;save optimization flag
  2044.         push af
  2045.         lhld loadad     ;save load address
  2046.         push hl
  2047.         lda eflag       ;save external addr given flag
  2048.         push af
  2049.         lhld exaddr     ;save external address if given
  2050.         push hl
  2051.         lhld curtop     ;save current top of memory
  2052.         push hl
  2053.  
  2054.         IF CPM
  2055.         lda ccpok       ;save CCP intact flag
  2056.         or a
  2057.         jp z,bt000
  2058.         ld a,1          ;set b0 to ccpok
  2059. bt000:  ld b,a          ;save in B
  2060.  
  2061.         lda oktort      ;get oktoret flag
  2062.         add a           ;put bit in b1 position
  2063.         add b           ;accumulate
  2064.         ld b,a          ;save it
  2065.  
  2066.         lda wboote      ;set b2 to wboote
  2067.         or a
  2068.         jp z,bt001
  2069.         ld a,4          ;if true, make b2 hi
  2070. bt001:  add b
  2071.  
  2072.         lda zenvf
  2073.         or a
  2074.         jp z,bt002
  2075.         ld a,8          ;set b3
  2076. bt002:  add b
  2077.  
  2078.         push af ;save combination of (b0 b1 b2 b3)
  2079.  
  2080.         ;lhld spsav     ;save CCP's stack pointer
  2081.         ;push hl
  2082.  
  2083.         lda werrs       ;if werrs false, just push erasub
  2084.         or a
  2085.         lda erasub
  2086.         jp z,setbt1
  2087.         or 2            ;if werrs true, but b1 high on erasub
  2088.        
  2089. setbt1: push af
  2090.         lhld defsub     ;save defsub/conpol bytes
  2091.         push hl
  2092.         lhld errbyt     ;get ZCPR3 error byte address
  2093.         push hl
  2094.  
  2095.         lhld curtop     ;put fcb address of cc2 fcb in BC
  2096.         ld de,-33
  2097.         add hl,de
  2098.         ld b,h
  2099.         ld c,l
  2100.         ENDIF
  2101.  
  2102.         jp tbuff        ;go do it
  2103.  
  2104. ;
  2105. ; This is the bootstrap that will run down at tbuff:
  2106. ;
  2107.  
  2108. bootcode:
  2109.         IF CPM          ;first the CP/M version...
  2110.         ld de,tpa       ;(cp/m only code is: 35 bytes)
  2111.         push de         ;save memory load address pointer
  2112.         push bc         ;save cc2's fcb address
  2113.         ld c,sdma       ;set DMA address to current memory load address (DE)
  2114.         call bdos
  2115.         pop de          ;pop cc2's fcb address into DE
  2116.         push de         ;and push back on stack for later
  2117.         ld c,rsequen    ;read a sector
  2118.         call bdos
  2119.         or a
  2120.         pop bc          ;pop cc2's fcb address into BC
  2121.         pop de          ;pop memory load address
  2122.         jp nz,postld    ;if done, go finish up
  2123.         ld hl,80h       ;otherwise add 80h to memory load address
  2124.         add hl,de
  2125.         ex de,hl                ;and put it back in DE
  2126.         jp tbuff+3
  2127.         ENDIF
  2128.  
  2129. ;
  2130. ; pop stuff off stack for CC2:
  2131. ;
  2132.  
  2133. postld:  equ tbuff + $ - bootcode
  2134.         IF CPM
  2135.         pop hl          ;get back wboote flag + extra byte
  2136.         shld ram+113h
  2137.         pop hl          ;get back defsub and conpol bytes
  2138.         shld ram+111h
  2139.         pop af          ;get back erasing submit files flag
  2140.         sta ram+10fh
  2141.         ENDIF
  2142.  
  2143.         ;pop hl         ;pop filename under MARC or saved SP under CP/M
  2144.         ;shld ram+010ah
  2145.  
  2146.         pop af          ;pop ccpok/maxmd flag
  2147.         sta ram+010eh
  2148.  
  2149.         pop hl          ;pop current top of memory address
  2150.         shld ram+010ch
  2151.  
  2152.         pop hl          ;pop external variables address
  2153.         shld ram+0107h
  2154.         pop af          ;pop external address flag
  2155.         sta ram+0109h
  2156.  
  2157.         pop hl          ;pop load address
  2158.         shld ram+0105h
  2159.         pop af          ;pop optimization flag
  2160.         sta ram+0104h
  2161.         pop af          ;pop output disk designation flag
  2162.  
  2163.         IF CPM
  2164.         sta fcb         ;set output disk designation
  2165.         ENDIF
  2166.  
  2167.         pop af          ;pop CDB flag
  2168.         sta ram+110h
  2169.  
  2170.         ld a,1
  2171.         sta ram+103h    ;set chained-to flag
  2172.         jp tpa          ;and go execute
  2173.  
  2174. bootlen: equ $-bootcode ;length of bootstrap
  2175.  
  2176. ;
  2177. ; (end of bootstrap)
  2178. ;
  2179.  
  2180.  
  2181.  
  2182.  
  2183. ldef:   ld de,-(st-6)
  2184.         lhld eofad
  2185.         add hl,de              
  2186.         inc hl
  2187.         ex de,hl                ;DE = length of text
  2188.         lhld curtop
  2189.         ld bc,-36
  2190.         add hl,bc
  2191.         ld b,h
  2192.         ld c,l          ;BC = destination
  2193.         push bc         ;save for later
  2194.         lhld eofad      ;HL = source
  2195. ldef1:  ld a,(hl)
  2196.         ld (bc),a
  2197.         dec bc
  2198.         dec hl
  2199.         dec de
  2200.         ld a,d
  2201.         or e
  2202.         jp nz,ldef1
  2203.         pop hl          ;get addr of where start addr goes
  2204.         inc hl          ;now HL = BDOS - 35
  2205.         ld (hl),c
  2206.         inc hl          ;and BDOS - 34
  2207.         ld (hl),b
  2208.         ret             ;and all done!
  2209.  
  2210.  
  2211.         IF LASM
  2212.         link ccc
  2213.         ENDIF
  2214.