Subversion Repositories NedoOS

Rev

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

  1. ;
  2. ;
  3. ; cc2a.asm
  4. ;
  5. ; 7/18/82: Added Kirkland debugging feature: if kflg (110h) is non-zero,
  6. ;          we assume it is the proper restart value to be inserted
  7. ;          at the start of each expression that is the first on a line,
  8. ;          to be followed by the line number.
  9. ;
  10. ; 12/30/85: Added new "modstk" module numbering/naming mechandsm as
  11. ;       previously implemented in CC.
  12. ;
  13.  
  14.  
  15.  
  16.         jp cc2          ;jump around data passed from call c,during autoload:
  17.  
  18.         IF CPM
  19. chainf: db 0            ;true if cc2 being auto-loaded by cc1 (103h)
  20.         ENDIF
  21.  
  22.         IF NOT CPM
  23. chainf: db 1            ;always being auto-loaded if under MARC
  24.         ENDIF
  25.  
  26. optimf: db 1            ;true if value-fetch hack is OK to perform (104h)
  27. cccadr: dw ram+100h     ;address of base of run-time package    (105h)
  28. exaddr: ds 2            ;explicit external address, (if eflag is true) (107h)
  29. eflag:  db 0            ;default to no explicit external address (109h)
  30.  
  31.         IF MARC
  32. fnam:   ds 2            ;pointer to filename for use in writing out crl file
  33.         ENDIF
  34.  
  35.         IF CPM
  36. ;spsav: ds 2            ;saved CCP stack pointer under CP/M (10Ah)
  37.         ds 2 ;NU (constant addresses!!!)
  38.         ENDIF
  39.  
  40. curtop: ds 2            ;current top of memory (10Ch)
  41.  
  42.         IF MARC
  43. maxmd:  db 0            ;maxmem done flag, under MARC
  44.         ENDIF
  45.  
  46.         IF CPM
  47. ccpok:  db 1            ;CCP still intact flag, under CP/M (10Eh)
  48.         ENDIF
  49.  
  50.         IF CPM
  51. erasub: db 0            ;bit 0: true if erasing submit files on error (10Fh)
  52.                         ;bit 1: "werrs" true if writing RED file
  53.         ENDIF
  54.  
  55.         IF NOT CPM
  56.         ds 1            ;dummy byte under MARC
  57.         ENDIF
  58.  
  59. cdbflg: db 0            ;CDB flag (-k<n> option to CC1) (110h)
  60.  
  61.         IF CPM
  62. defsub: db 0            ;where to find submit files (CP/M only) (111h)
  63. conpol: db 1            ;whether or not to poll console for interrupts (112h)
  64. errbyt: dw errdum       ;ZCPR3 error condition flag address (dummy default)
  65.         ENDIF
  66.  
  67.  
  68.         IF NOT CPM
  69.         ds 4
  70.         ENDIF
  71.  
  72. oktort: db 0            ;extracted from ccpok b1 on startup
  73. wboote: db 1            ;extracted from ccpok b2 on startup
  74. zenvf:  db 0            ;extracted from ccpok b3 on startup
  75.  
  76. errdum: ds 1            ;dummy zcpr3 error flag
  77.  
  78.  
  79. cc2:    ;ld hl,0                ;save current SP in HL
  80.         ;add hl,sp
  81.         ld sp,0;stack   ;set up new stack
  82.  
  83.         IF CPM
  84.         lda defsub
  85.         inc a
  86.         sta subfile
  87.         ENDIF
  88.  
  89.         lda chainf     
  90.         or a
  91.         jp z,cc2a               ;if not chaining, go initialize stuff
  92.  
  93.                         ; UNPACK ccpok:
  94.  
  95.         lda ccpok       ;extract oktort from ccpok
  96.         ld b,a
  97.         and 1           ;b0
  98.         sta ccpok       ;set ccpok flag
  99.  
  100.         ld a,b
  101.         and 2           ;b1
  102.         rrca
  103.         sta oktort      ;set ok to return to ccp flag
  104.  
  105.         ld a,b
  106.         and 4           ;b2
  107.         rrca
  108.         rrca
  109.         sta wboote      ;set do warm boot on exit flag
  110.  
  111.         ld a,b
  112.         and 8           ;b3
  113.         rrca
  114.         rrca
  115.         rrca
  116.         sta zenvf       ;set ZCPR3 flag
  117.  
  118.         or a            ;Z environment?
  119.         jp nz,cc20a     ;if not, go do greeting
  120.  
  121.         ld hl,errdum    ;else set errbyt address to dummy
  122.         shld errbyt
  123.  
  124. cc20a:  ld de,s00       ;print CR-LF if being chained to from cc1
  125.         call pstgco     ;if chaining, print CR-LF before sign-on message
  126.         jp cc2b
  127.  
  128. cc2a:   ;shld spsav     ;save CCP stack pointer
  129.         ld hl,NEDOOSMEMTOP;lhld ram+6
  130.         shld curtop     ;set up current top of memory below CCP
  131.         ld a,1
  132.         sta ccpok       ;set CCP not bashed flag
  133.        
  134. cc2b:   lhld errbyt
  135.         ld (hl),0               ;no error by default
  136.  
  137.         ld de,s0        ;regular sign-on msg
  138.         call pstgco
  139.  
  140.         call c2init     ;do rest of initialization
  141.  
  142. cc2c:   call dofun      ;process a function
  143.         lhld cdp
  144.         call igshzz     ;lde pointer to next function
  145.         shld cdp        ;and save text pointer
  146.         ld a,(hl)               ;get 1st char of next function
  147.         ld hl,entn      ;bump entry count (function count)
  148.         inc (hl)
  149.         or a
  150.         jp nz,cc2c      ;are we at EOF?
  151.  
  152.         lhld codp       ;yes.
  153.         dec hl
  154.         shld eofad      ;set this for the "writf" routine
  155.  
  156.         call errwrp     ;wrap up error handling, exit if there were errors
  157.  
  158.         ld hl,ascb+4    ;else do write out a CRL file...
  159.         ld (hl),'K'     ;but first give a usage report
  160.  
  161.         IF CPM
  162.         ld hl,NEDOOSMEMTOP;lhld bdosp   ;this is as high as free memory can ever get
  163.         ld l,0
  164.         ENDIF
  165.  
  166.         ex de,hl
  167.         lhld codp       ;and this is as high as we got generating code
  168.         call cmh
  169.         add hl,de
  170.         ld a,h          ;divide difference by 1K
  171.         rra
  172.         rra
  173.         and 3fh
  174.         ld l,a          ;and print out result
  175.         ld h,0
  176.         dec hl
  177.         xor a
  178.         call prhcs      ;print out their difference
  179.         ld de,stgtsp    ;with some text
  180.         call pstg       ;and...
  181.  
  182.         call writf      ;write out the CRL file
  183.  
  184.         IF CPM
  185. exit:   QUIT ;lda wboote        ;do warm boot on exit?
  186.         ;or a
  187.         ;jp nz,ram              ;if so, go boot
  188.  
  189.         ;lda chainf     ;did we chain?
  190.         ;or a
  191.         ;jp z,ram               ;if not, do warm boot in case we're SID-ing
  192.  
  193.         ;lhld spsav     ;get possibly saved CCP SP
  194.         ;ld sp,hl
  195.  
  196.         ;lda ccpok      ;CCP intact?
  197.         ;or a
  198.         ;ret nz         ;return if so
  199.  
  200.         ;lda oktort     ;ok to return DESPITE ccpok's value?
  201.         ;or a
  202.         ;ret nz         ;if so, return
  203.  
  204.         ;jp ram         ;else warm-boot
  205.        
  206.         ENDIF
  207.  
  208.  
  209. ;
  210. ; Some standard routine addresses within C.CCC, all relative
  211. ; to the origin of C.Ccall c,(stored at cccadr at run time)
  212. ; These values will change anytime C.Ccall c,is reconfigured.
  213. ;
  214.  
  215. ldei:   equ 04dh        ;value-fetch routines
  216. sdei:   equ 05ch
  217. lsei:   equ 06bh
  218. ssei:   equ 077h
  219. ldli:   equ 083h
  220. sdli:   equ 090h
  221.  
  222.  
  223. pzinh:  equ 09dh                ;flag conversion routines
  224. pnzinh: equ pzinh+6
  225. pcinh:  equ pzinh+12
  226. pncinh: equ pzinh+18
  227. ppinh:  equ pzinh+24
  228. pminh:  equ pzinh+30
  229. pzind:  equ pzinh+36
  230. pnzind: equ pzinh+42
  231. pcind:  equ pzinh+48
  232. pncind: equ pzinh+54
  233. ppind:  equ pzinh+60
  234. pmind:  equ pzinh+66
  235.  
  236. eqwel:  equ 0e5h        ;relational operator routines
  237.  
  238. blau:   equ 0ebh
  239. albu:   equ blau+1
  240.  
  241. bgau:   equ 0f2h
  242. agbu:   equ bgau+1
  243.  
  244. blas:   equ 0f9h
  245. albs:   equ blas+1
  246.  
  247. bgas:   equ 104h
  248. agbs:   equ bgas+1
  249.  
  250.  
  251. smod:   equ 10fh
  252. usmod:  equ 129h
  253. smul:   equ 13fh        ;multaplicative operator routines
  254. usmul:  equ 16bh
  255. usdiv:  equ 189h
  256. sdiv:   equ 1cbh
  257.  
  258.  
  259. sderbl: equ 1e4h        ;shift operator routines
  260. shlrbe: equ sderbl+1
  261. sdelbl: equ 1f2h
  262. shllbe: equ sdelbl+1
  263.  
  264.  
  265. cmhl:   equ 1fah        ;2's complement routines
  266. cmd:    equ 202h
  267.  
  268.  
  269.  
  270. ;
  271. ; Keyword codes
  272. ;
  273.  
  274. gotcd:  equ 8dh         ;goto
  275. rencd:  equ 8eh         ;return
  276. sizcd:  equ 8fh         ;sizeof
  277. brkcd:  equ 90h         ;break
  278. cntcd:  equ 91h         ;continue
  279. ifcd:   equ 92h         ;if
  280. elscd:  equ 93h         ;else
  281. docd:   equ 95h         ;do
  282. whlcd:  equ 96h         ;while
  283. swtcd:  equ 97h         ;switch
  284. lbrcd:  equ 9bh         ;{
  285. rbrcd:  equ 9ch         ;}
  286. mainc:  equ 9dh         ;main
  287. pplus:  equ 0b2h        ;++
  288. mmin:   equ 0b3h        ;--
  289. arrow:  equ 0b4h        ;->
  290. mincd:  equ 0b5h        ;-
  291. mulcd:  equ 0b6h        ;*
  292. divcd:  equ 0b7h        ;/
  293. ancd:   equ 0bbh        ;&
  294. letcd:  equ 0beh        ;=
  295. notcd:  equ 0bfh        ;!
  296. open:   equ 0c2h        ;(
  297. close:  equ 0c3h        ;)
  298. plus:   equ 0c4h        ;+
  299. period: equ 0c5h        ;.
  300. semi:   equ 0c6h        ;";"
  301. comma:  equ 0c7h        ;,
  302. openb:  equ 0c8h        ;[
  303. closb:  equ 0c9h        ;]
  304. colon:  equ 0cah        ;:
  305. circum: equ 0cbh        ;~
  306. qmark:  equ 0c0h        ;?
  307. slcd:   equ 0b0h        ;<<
  308. srcd:   equ 0b1h        ;>>
  309. lecd:   equ 0aeh        ;<=
  310. gecd:   equ 0afh        ;>=
  311. eqcd:   equ 0aah        ;==
  312. neqcd:  equ 0abh        ; <excl.pt.>=
  313. modcd:  equ 0b8h        ;%
  314. gtcd:   equ 0b9h        ;>
  315. ltcd:   equ 0bah        ;<
  316. xorcd:  equ 0bch        ;^
  317. orcd:   equ 0bdh        ;|
  318. andand: equ 0ach        ;&&
  319. oror:   equ 0adh        ;||
  320.  
  321.  
  322. ;
  323. ; Text strings:
  324. ;
  325.  
  326. s1:     db 'Can''t open file+'
  327. s2:     db cr,lf,'Write error+'
  328. s2a:    db 'CRL Dir overflow: break up source file+'
  329. s3:     db 'Missing label+'
  330. s4:     db 'Missing semicolon+'
  331. s4a:    db 'Extra text after statement, before ";"+'
  332. stgms:  equ s4  ;a more mnemonic name for this error msg
  333. s5:     db 'Illegal statement+'
  334. s6:     db 'Can''t create CRL file+'
  335. stg7:   db 'Bad operator+'
  336. stg8:   db 'Lvalue required+'
  337. stg8a:  db '++ or -- operator needs Lvalue+'
  338. stg8b:  db 'Bad left operand in assignment expr.+'
  339. stg9:   db 'Mismatched parens+'
  340. stg9a:  db 'Mismatched brackets+'
  341. stg10:  db 'Bad expression+'
  342. stg11:  db 'Bad function name+'
  343. stg13:  db 'Bad arg to unary op+'
  344. stg14:  db 'Expecting ":"+'
  345. stg15:  db 'Bad subscript+'
  346. stg16:  db 'Bad array base+'
  347. stg17:  db 'Bad struct or union spec+'
  348. stg17a: db 'Using undefined struct type+'
  349. stg18:  db 'Bad type in binary operation+'
  350. stg19:  db 'Bad struct or union member+'
  351. stg20:  db 'Bad member name+'
  352. stg21:  db 'Illegal indirection+'
  353. stgie:  db 'Internal error: garbage in file or bug in C+'
  354. stgom:  db 'Sorry, out of memory. Break it up!+'
  355. stgeof: db 'Encountered EOF unexpectedly+'
  356. stgbf:  db 'Bad parameter list+'
  357. stgeri: db cr,lf,'RED error output initiated+'
  358.  
  359.         IF CPM
  360. stgabo: db 'Compilation aborted by ^C+'
  361.         ENDIF
  362.  
  363.         IF NOT CPM
  364. stgabo: db 'Compilation aborted+'
  365.         ENDIF
  366.  
  367. stgbbo: db 'Expecting binary op+'
  368. stgeop: db 'Missing "("+'
  369. stgecp: db 'Missing ")"+'
  370.  
  371. stgtsp: db 'to spare',cr
  372.         IF MARC
  373.            db lf
  374.         ENDIF
  375.         db 0
  376.  
  377. stgftb: db 'The function ',0
  378. stgtb2: db ' is too complex; break it into smaller ones+'
  379. stgmlb: db 'Missing "{" in function def''n+'
  380. stgcsn: db 'Control Structure '
  381. stgetc: db 'Nesting too deep+'
  382.  
  383.         IF CPM
  384. subfile: db 1,'$$$     SUB',0,0,0,0
  385.         ENDIF
  386.  
  387. s00:    db cr,lf,0
  388.  
  389. patch:  dw 0,0,0,0,0,0,0,0,0,0ffffh     ;patch space
  390. patch2: dw 0,0,0,0,0,0,0,0ffffh
  391. patch3: dw 0,0,0,0,0,0,0ffffh
  392.  
  393.  
  394. ;
  395. ; Special codes
  396. ;
  397.  
  398. nlcd:   equ 0f7h        ;new-line (linefeed)
  399. concd:  equ 0f8h        ;constant code (followed by 2 byte value)
  400. varcd:  equ 0f9h        ;variable code (foll. by 2 byte disp into s.t.)
  401. lblcd:  equ 0fah        ;label code (foll. by 2-byte label val)
  402. labrc:  equ 0fch        ;label reference (foll. by 2-byte label code value)
  403. strcd:  equ 0fdh        ;string code (foll. by 2-byte sting #)
  404. swtbc:  equ 0feh        ;byte following `switch(expr)', preceding case table
  405.  
  406. litrl:  equ 0f7h
  407. endms:  equ 38h
  408.  
  409. modbeg: equ 0f5h
  410. modend: equ 0f6h
  411.  
  412.  
  413.  
  414. minit:  lda optimf      ;look at rst7 bit of optimization flag
  415.         and 40h
  416.         ret z           ;if not set, don't fudge with macro table
  417.         ld hl,m16bz
  418.         shld mactz
  419.         shld mactz+2
  420.         ld hl,m18z
  421.         shld mactz+4
  422.         shld mactz+6
  423.         ret
  424.  
  425.  
  426. ;
  427. ; Come here on an internal error (if ierror is called instead
  428. ; of jumped to, that makes it easier to find out where the
  429. ; internal error occurred)
  430. ;
  431.  
  432. ierror: ld de,stgie     ;come here when things are REALLY skewered
  433.  
  434. ;
  435. ; Print out error and abort compilation:
  436. ;
  437.  
  438. perrab: call perr
  439.  
  440.  
  441. ;
  442. ; The general abort entry point...abort submit processing
  443. ; and reboot.
  444. ;
  445.  
  446. errab:  push hl
  447.         lhld errbyt
  448.         ld (hl),1               ;set zcpr3 error flag (or dummy under CP/M)
  449.         pop hl
  450.        
  451.         lda werrs
  452.         or a
  453.         call nz,errwr2
  454.  
  455. errab2:
  456.         ld a,7          ;ring a bell for errors having occurred
  457.         call outch
  458.         lda erasub      ;bother to erase submit files?
  459.         or a
  460.         jp z,exit               ;if not, all done
  461.  
  462.         ;ld c,sguser    ;get current user
  463.         ;ld e,0ffh
  464.  
  465.         ;push af        ;save current user
  466.  
  467.         ;ld c,sguser    ;select user 0
  468.         ;ld e,0
  469.         ;lda zenvf      ;but only under ZSYSTMS!
  470.         ;or a
  471.         ;call nz,bdos
  472.  
  473.         ld de,subfile   ;erase pending submit files
  474.         call delf2
  475.  
  476.         ;pop af         ;get original user
  477.         ;ld e,a
  478.         ;ld c,sguser    ;select original user
  479.         ;call bdos
  480.  
  481.         jp exit ;all done
  482.  
  483.  
  484. ;
  485. ; Routine that expects a semicolon to be the next non-space
  486. ; character in the text. If it isn't, spew an error. If it
  487. ; is, pass over it:
  488. ;
  489.  
  490. psemi:  call igsht
  491.         cp semi
  492.         jp nz,psmi2
  493.         inc hl
  494.         ret
  495.  
  496. psmi2:  push hl
  497.         lhld nlcnt      ;get current line number
  498.         ex (sp),hl              ;put in on stack, get text ptr in HL
  499.         call fsemi      ;advance to semicolon
  500.         ex (sp),hl              ;push text ptr onto stack, get old line no. in HL
  501.         ex de,hl                ;put old line no. in DE
  502.         lhld nlcnt      ;get current line no.
  503.         call cmpdh     
  504.         pop hl          ;get back current text ptr
  505.         ld de,s4
  506.         jp nz,psmi3     ;if no semicolon on current line, complain about
  507.                         ; missing semicolon
  508.         ld de,s4a       ;else complain about superfluous characters    
  509. psmi3:  call perr
  510.         inc hl          ;advance text ptr past semicolon
  511.         ret
  512.  
  513.  
  514. ;
  515. ; Routine to skip everything until a semicolon is found (used
  516. ; mainly in error-recovery following the detection of a really
  517. ; screwy, non-cleanly-recoverable error):
  518. ;
  519.  
  520. fsemi:  ld a,(hl)
  521.         or a
  522.         jp z,igshe1     ;if EOF, bad error
  523.         cp semi
  524.         ret z
  525.  
  526.         ld de,s5
  527.         cp lbrcd
  528.         jp z,perrab
  529.         cp rbrcd
  530.         jp z,perrab
  531.  
  532.         cp nlcd
  533.         jp nz,fsemi3
  534.         push hl
  535.         lhld nlcnt
  536.         inc hl
  537.         shld nlcnt
  538.         pop hl
  539. fsemi3: call cdtst
  540.         jp c,fsemi5
  541.         inc hl
  542.         inc hl
  543. fsemi4: inc hl
  544.         jp fsemi
  545.  
  546. fsemi5: cp modbeg
  547.         jp nz,fsemi4
  548.         push de
  549.         ld de,13
  550.         add hl,de
  551.         pop de
  552.         jp fsemi
  553.  
  554.  
  555. ;
  556. ; Given HL->text, pass by any special codes and white space:
  557. ;
  558.  
  559. pascd:  call igsht
  560.         call cdtst
  561.         ret c
  562.         inc hl
  563.         inc hl
  564.         inc hl
  565.         jp pascd
  566.  
  567. igcd:   equ pascd
  568.  
  569. pascd2: call igshzz
  570.         or a
  571.         ret z
  572.         call cdtst
  573.         jp nc,pscd3
  574.         or a
  575.         ret
  576. pscd3:  inc hl
  577.         inc hl
  578.         inc hl
  579.         or a
  580.         jp pascd2
  581.  
  582. cdtst:  cp 0f8h
  583.         ret c
  584.         cp 0feh
  585.         ccf
  586.         ret
  587.  
  588. ;
  589. ; Ignore white space in text (but acknowledge newlines
  590. ;  by bumping line count when they're encountered), and handle
  591. ; modbeg/modend:
  592. ;
  593.  
  594. igsht:  call igshzz
  595.         or a
  596.         ret nz
  597.         lda prnflg      ;file ends inside parens or brackets?
  598.         or a
  599.         jp z,igshe1
  600.  
  601.         ld de,stg9      ;yes...if prnflag is 1, then use parens message
  602.         dec a
  603.         jp z,igsht0    
  604.         ld de,stg9a     ;else use brackets message
  605.  
  606. igsht0: lhld prnsav
  607.         shld nlcnt
  608.         jp perrab
  609.  
  610. igshe1: ld de,stgeof
  611. igshe2: jp perrab
  612.  
  613. igshzz: ld a,(hl)
  614.         or a
  615.         ret z
  616.         cp nlcd
  617.         jp nz,igsh2
  618.         push hl         ;bump newline count
  619.         lhld nlcnt
  620.         inc hl
  621.         shld nlcnt
  622.         pop hl
  623.         inc hl
  624.         jp igshzz
  625.  
  626. igsh2:  cp lblcd
  627.         jp nz,igsh3
  628.         push de
  629.         inc hl
  630.         ld e,(hl)
  631.         inc hl
  632.         ld d,(hl)
  633.         inc hl
  634.         call entl
  635.         pop de
  636.         jp igshzz
  637.  
  638. igsh3:  cp ' '
  639.         jp nz,igsh4
  640. igsh3a: inc hl
  641.         jp igshzz
  642.  
  643. igsh4:  cp modbeg       ;module begin?
  644.         jp nz,igsh5
  645.         inc hl
  646.         call pushmn     ;push module name on module stack
  647.         jp igshzz
  648.  
  649. igsh5:  cp modend       ;module end?
  650.         ret nz
  651.         call popmn      ;pop module name
  652.         jp igsh3a
  653.  
  654. ;
  655. ; Push module name at HL onto modstk, save current line number
  656. ; after it in the module stack, bump modstc, and reset nlcnt:
  657. ;
  658.  
  659. pushmn: ex de,hl        ;put text ptr in DE
  660.         push hl ;save HL
  661.         ld hl,modstc
  662.         inc (hl)
  663.         lhld modstp
  664.         ld b,12
  665.         call ldrc
  666.         push de
  667.         ex de,hl
  668.         lhld nlcnt
  669.         ex de,hl
  670.         ld (hl),e
  671.         inc hl
  672.         ld (hl),d
  673.         inc hl
  674.         shld modstp
  675.         ld hl,0
  676.         shld nlcnt
  677.         pop de
  678.         pop hl
  679.         ex de,hl
  680.         ret
  681.                
  682. ;
  683. ; Pop modstk entry:
  684. ;
  685.  
  686. popmn:  push hl
  687.         push de
  688.         lhld modstp
  689.         dec hl
  690.         ld d,(hl)
  691.         dec hl
  692.         ld e,(hl)
  693.         ex de,hl
  694.         shld nlcnt
  695.         ld hl,-12
  696.         add hl,de
  697.         shld modstp
  698.         ld hl,modstc
  699.         dec (hl)
  700.         pop de
  701.         pop hl
  702.         ret
  703.  
  704. ;
  705. ; lde B bytes from (DE) to (HL):
  706. ;
  707.  
  708. ldrc:   push af
  709. ldrc1:  ld a,(de)
  710.         ld (hl),a
  711.         inc hl
  712.         inc de
  713.         dec b
  714.         jp nz,ldrc1
  715.         pop af
  716.         ret            
  717.  
  718.  
  719. ;
  720. ; Peek forward to next token, without actually processing any
  721. ; codes or changing status of the text pointer from the current value:
  722. ;
  723.  
  724. peeknxt:
  725.         push hl         ;save text pointer
  726.         push de
  727.         dec hl
  728. peekn1: inc hl          ;look at next char
  729. peekn2: ld a,(hl)               ;if null, done
  730.         or a
  731.         jp z,peekn4
  732.         cp nlcd ;ignore all whitespace and codes
  733.         jp z,peekn1
  734.         call cdtst
  735.         jp c,peekn3
  736.         inc hl
  737.         inc hl
  738.         jp peekn1
  739. peekn3: cp ' '
  740.         jp z,peekn1
  741.         cp modend
  742.         jp z,peekn1
  743.         cp modbeg
  744.         jp nz,peekn4
  745.         ld de,13
  746.         add hl,de
  747.         jp peekn2      
  748. peekn4: pop de
  749.         pop hl
  750.         ret
  751.  
  752.  
  753. ;
  754. ; Given that HL->open paren in text, find the matching
  755. ; close paren and pass by it (if no matching paren is ever
  756. ; found, announce an error ocurring on original line where
  757. ; the open paren was found):
  758. ;
  759.  
  760. mtchp:  ld a,1
  761.         sta prnflg
  762.         push hl
  763.         lhld nlcnt
  764.         shld prnsav
  765.         pop hl
  766.         call mtchpz
  767.         push af
  768.         xor a
  769.         sta prnflg
  770.         pop af
  771.         ret
  772.  
  773. mtchpz: inc hl
  774.         call igcd
  775.         cp close
  776.         jp nz,mtcp2
  777.         inc hl
  778.         ret
  779.  
  780. mtcp2:  cp open
  781.         jp nz,mtchpz
  782.         call mtchpz
  783.         dec hl
  784.         jp mtchpz
  785.  
  786. ;
  787. ; Similar to mtchp, except for square brackets instead:
  788. ;
  789.  
  790. mtchb:  ld a,2
  791.         sta prnflg
  792.         push hl
  793.         lhld nlcnt
  794.         shld prnsav
  795.         pop hl
  796.         call mtchbz
  797.         push af
  798.         xor a
  799.         sta prnflg
  800.         pop af
  801.         ret
  802.  
  803.  
  804. mtchbz: inc hl
  805.         call igcd
  806.         cp closb
  807.         jp nz,mtcbz2
  808.         inc hl
  809.         ret
  810.  
  811. mtcbz2: cp openb
  812.         jp nz,mtchbz
  813.         call mtchbz
  814.         dec hl
  815.         jp mtchbz
  816.  
  817. ;
  818. ; Convert ASCII character in A to upper case,
  819. ; but don't change value of parity bit!
  820. ;
  821.  
  822. mapuc:  push bc
  823.         ld b,a
  824.         and 7fh
  825.         call mapuc2
  826.         ld c,a
  827.         ld a,b
  828.         and 80h
  829.         or c            ;OR in original parity bit
  830.         pop bc
  831.         ret
  832.  
  833. mapuc2: cp 61h
  834.         ret c
  835.         cp 7bh
  836.         ret nc
  837.         sub 32
  838.         ret
  839.  
  840. ;
  841. ; Return Cy set if (DE < HL)
  842. ;
  843.  
  844.  
  845. cmpdh:  ld a,d
  846.         cp h
  847.         ret nz
  848.         ld a,e
  849.         cp l
  850.         ret
  851.  
  852.  
  853. ;
  854. ; Print error message, but use the line number saved at "savnlc" instead
  855. ; of the standard "nlcnt" count:
  856. ;
  857.  
  858. perrsv: push    hl              ;save current text pointer
  859.         lhld    nlcnt           ;save current line count
  860.         push    hl
  861.         lhld    savnlc          ;get saved line count
  862.         shld    nlcnt           ;make it current just for this
  863.         call    perr
  864.         pop     hl              ;now restore everything
  865.         shld    nlcnt
  866.         pop     hl
  867.         ret                     ;and return
  868.  
  869.  
  870. ;
  871. ; Report error by first printing out the current line number followed
  872. ; by a colon and a space, and then printing out the string pointed to
  873. ; by DE on entry:
  874. ;
  875.  
  876. perr:   ld a,1
  877.         sta errf
  878.         lda prerrs      ;print error msgs?
  879.         or a
  880.         ret z           ;return if not
  881.         push hl
  882.         call pmodnc     ;print module name, colon, space
  883.         lhld nlcnt
  884.         call prhcs
  885.         call pstg
  886.         pop hl
  887.         ret
  888.  
  889.  
  890. ;
  891. ; Print out current module name, followed by a colon and space
  892. ;
  893.  
  894. pmodnc: call pmodnm
  895.         push af
  896.         ld a,':'
  897.         call outch
  898.         ld a,' '
  899.         call outch
  900.         pop af
  901.         ret
  902.  
  903. ;
  904. ; Print out current module name:
  905. ;
  906.  
  907. pmodnm: push hl
  908.         push de
  909.         lhld modstp
  910.         ld de,-14
  911.         add hl,de
  912.         ex de,hl
  913.         call pfnam2
  914.         pop de
  915.         pop hl
  916.         ret
  917.  
  918.  
  919. ;
  920. ; Print out filename of fcb at DE:
  921. ;
  922.  
  923.  
  924. pfnam2: push bc
  925.         ld a,(de)               ;get disk code
  926.         or a
  927.         jp z,pfnm3      ;if file on currently logged disk, don't print
  928.                         ;disk designator.
  929.  
  930. ;       ld c,gdisk      ;This section of code commented out to keep
  931. ;       push de         ;files on the currently logged drive from having
  932. ;       call bdos       ;a disk designator printed before their names.
  933. ;       pop de          ;uncomment the code to put this feature back
  934. ;       inc a           ;into action.
  935.  
  936. pfnm2:  add a,'@'               ;get A = 'A' for drive A, 'B' for B, etc.
  937.         call outch
  938.         ld a,':'
  939.         call outch
  940. pfnm3:  inc de
  941.         ld b,8
  942.         call pnseg
  943.         ld a,(de)
  944.         cp ' '
  945.         ld a,'.'        ;print dot only if filename has extension
  946.         call nz,outch
  947.         ld b,3
  948.         call pnseg
  949.         pop bc
  950.         ret
  951.  
  952. pnseg:  ld a,(de)
  953.         cp ' '
  954.         call nz,outch
  955.         inc de
  956.         dec b
  957.         jp nz,pnseg
  958.         ret
  959.  
  960.  
  961. ;
  962. ; Print out the null-terminated string pointed to by DE:
  963. ;
  964.  
  965. pstg:   ld a,(de)
  966.         or a
  967.         ret z
  968.         cp '+'
  969.         jp nz,pstg2
  970.         ld a,cr
  971.         call outch
  972.         ld a,lf
  973.         jp outch
  974.  
  975. pstg2:  call outch
  976.         inc de
  977.         jp pstg
  978.  
  979.  
  980. ;
  981. ; Output a string to console only:
  982. ;
  983.  
  984. pstgco: lda werrs
  985.         push af
  986.         xor a
  987.         sta werrs
  988.         call pstg
  989.         pop af
  990.         sta werrs
  991.         ret
  992.  
  993. ;
  994. ; Output a character of text to the console and/or PROGERRS.$$$ file:
  995. ;
  996.  
  997. outch:  push de
  998.         push bc
  999.         push hl
  1000.         push af
  1001.  
  1002.         ld e,a          ;lde char to be output to E register
  1003.  
  1004.         lda werrs
  1005.         or a            ;if not writing errs to PROGERRS file,
  1006.         jp z,outch3     ;       go write to console
  1007.        
  1008.         lda errsin
  1009.         or a
  1010.         jp nz,outch1    ;if RED buffer initialized, go handle I/O
  1011.                         ;else initialize RED buffer:
  1012.         inc a
  1013.         sta errsin
  1014.  
  1015.         push de
  1016.         ld de,redfcb
  1017.         lda fcb
  1018.         ld (de),a
  1019.         call delf2      ;delete previous PROGERRS.$$$
  1020.         call create2    ;create new one
  1021. ;       call fopen2     ;open for output
  1022.         ld hl,redbuf
  1023.         shld redbp      ;initialize redbuf sector pointer
  1024.  
  1025.         ld de,stgeri    ;"RED error output initiated"
  1026.         call pstgco     ;print text to console only
  1027.         pop de
  1028.  
  1029. outch1: call redout     ;write char to red output file
  1030.  
  1031. outch3: ;ld c,conout
  1032.         ;call bdos
  1033.         ld a,e
  1034.         PRCHAR
  1035.  
  1036.         pop af
  1037.         pop hl
  1038.         pop bc
  1039.         pop de
  1040.         ret
  1041.  
  1042. ; Write a character to RED output buffer, flushing if needed:
  1043.  
  1044. redout: lhld redbp      ;get redbuf pointer
  1045.         ld (hl),e               ;store char
  1046.         inc hl          ;bump pointer
  1047.         shld redbp      ;save pointer
  1048.         ld a,l          ;past end of buffer?
  1049.         cp (redbuf+128) and 0ffh
  1050.         ret nz          ;if not, return
  1051.  
  1052.  
  1053.  
  1054. redwrt: push de
  1055.         ld de,redbuf    ;set DMA address to redbuf for sector write
  1056.         ld c,sdma
  1057.         call bdos
  1058.  
  1059.         ld de,redfcb
  1060.         call writs2     ;write sector
  1061.  
  1062.         ld de,tbuff     ;set DMA address back for normal file i/o
  1063.         ld c,sdma
  1064.         call bdos
  1065.  
  1066.         ld hl,redbuf
  1067.         shld redbp     
  1068.         pop de
  1069.         ret
  1070.                
  1071.  
  1072. ; Wrap up error handling, exit if there were errors:
  1073.  
  1074. errwrp: call errwr1
  1075.         xor a
  1076.         sta werrs
  1077.         ret
  1078.  
  1079. errwr1: lda errf        ;were there any errors?
  1080.         or a
  1081.         ret z           ;return if no errors
  1082.  
  1083.         lda werrs       ;RED output enabled?
  1084.         or a
  1085.         jp z,errab2     ;if not, we're all done.
  1086.  
  1087. errwr2: lda errsin
  1088.         or a
  1089.         ld hl,stgie     ;if errf true but RED buf not initialized,
  1090.         call z,perrab   ; some kind of internal error
  1091.         ld e,1ah        ;ascii end-of-file
  1092.         call redout
  1093.         lhld redbp
  1094.         ld a,l
  1095.         cp redbuf and 0ffh      ;has buffer just been flushed?
  1096.         call nz,redwrt  ;if not, write buffer one last time
  1097.         ld de,redfcb
  1098.         call fclose2    ;close RED output buffer
  1099.         jp errab2
  1100.  
  1101.  
  1102. ;
  1103. ; Print a newline to the console:
  1104. ;
  1105.  
  1106. crlf:   push af
  1107.         ld a,cr
  1108.         call outch
  1109.         ld a,lf
  1110.         call outch
  1111.         pop af
  1112.         ret
  1113.  
  1114.  
  1115. ;
  1116. ; Print out the value in HL in hex, followed by a colon
  1117. ; and a space.
  1118. ; Upon entry, A non-0: print no leading spaces
  1119. ;              A == 0: print leading spaces making total textual output 4 chars
  1120. ;
  1121. ;
  1122.  
  1123. prhcs:  push hl
  1124.         push de
  1125.         push af
  1126.         call prh        ;convert HL to ascii at ascb
  1127.         pop af
  1128.         or a
  1129.         ld hl,ascb
  1130.         jp z,prhcs3     ;if printing leading spaces, go do it
  1131.  
  1132.         dec hl
  1133. prhcs1: inc hl
  1134.         ld a,(hl)
  1135.         cp ' '
  1136.         jp z,prhcs1     ;if all four digits, no leading spaces needed
  1137.  
  1138. prhcs3: ex de,hl                ;put text ptr in DE
  1139.         call pstg
  1140.         pop de
  1141.         pop hl
  1142.         ret
  1143.  
  1144.  
  1145. ;
  1146. ; Convert Hex value in HL to ASCII, at ASCB, followed by a colon
  1147. ; and a space. A kludgey gas-pump algorithm is used, since
  1148. ; no big numbers are ever printed (only line numbers):
  1149. ;
  1150.  
  1151.  
  1152. prh:    push de
  1153.         call prh00
  1154.         pop de
  1155.         ret
  1156.  
  1157. prh00:  push hl
  1158.         ld hl,'  '
  1159.         shld ascb
  1160.         ld hl,' 0'
  1161.         shld ascb+2
  1162.         pop hl
  1163.         inc hl
  1164. prh0:   ld a,h
  1165.         or l
  1166.         ret z
  1167.         dec hl
  1168.         push hl
  1169.         ld hl,ascb+3
  1170. prh1:   ld a,(hl)
  1171.         cp ' '
  1172.         jp nz,prh2
  1173.         ld a,'0'
  1174. prh2:   inc a
  1175.         cp '9'+1
  1176.         jp z,prh4
  1177. prh3:   ld (hl),a
  1178.         pop hl
  1179.         jp prh0
  1180. prh4:   ld (hl),'0'
  1181.         dec hl
  1182.         jp prh1
  1183.  
  1184.  
  1185. fopen:
  1186.         IF CPM
  1187.         ld de,fcb
  1188.  
  1189. fopen2: push de
  1190.         ld c,openfil
  1191.         call bdos
  1192.         cp 255
  1193.         pop de
  1194.         jp z,op2
  1195.         push hl ;clear nr field
  1196.         ld hl,32
  1197.         add hl,de
  1198.         ld (hl),0
  1199.         pop hl
  1200.         ret
  1201.         ENDIF
  1202.  
  1203.         IF NOT CPM
  1204.         ld c,m$open
  1205.         call msys
  1206.         sta marcfd
  1207.         ret z
  1208.         jp ferrab
  1209.         ENDIF
  1210.  
  1211. op2:    ld de,s1
  1212.         call pstg
  1213.         jp errab
  1214.  
  1215. fclose: ld de,fcb
  1216.  
  1217.         IF CPM
  1218. fclose2:
  1219.         push hl
  1220.         ld c,closefil
  1221.         call bdos
  1222.         ENDIF
  1223.  
  1224.         IF NOT CPM
  1225.         ld c,m$close
  1226.         lda marcfd
  1227.         call msys
  1228.         jp nz,ferrab
  1229.         ENDIF
  1230.  
  1231.         pop hl
  1232.         ret
  1233.  
  1234. writs:
  1235.         ld de,fcb
  1236.  
  1237.         IF CPM          ;write a sector under CP/M
  1238. writs2: push hl
  1239.         ld c,wsequen
  1240.         call bdos
  1241.         pop hl
  1242.         or a
  1243.         ret z
  1244.         ENDIF
  1245.  
  1246.         IF NOT CPM
  1247.         ld c,m$write
  1248.         lda marcfd
  1249.         call msys
  1250.         ret z
  1251.         jp ferrab
  1252.         ENDIF
  1253.  
  1254.         ld de,s2
  1255.         call pstg
  1256.         jp errab
  1257.  
  1258.  
  1259. reads:  push hl
  1260.        
  1261.         IF CPM
  1262.         ld de,fcb
  1263.         ld c,rsequen
  1264.         call bdos
  1265.         pop hl
  1266.         or a
  1267.         ret z
  1268.         scf
  1269.         ret
  1270.         ENDIF
  1271.  
  1272.         IF NOT CPM
  1273.         lda marcfd
  1274.         ld c,m$read
  1275.         ld hl,tbuff
  1276.         ld de,128
  1277.         call msys
  1278.         jp nz,ferrab
  1279.         pop hl
  1280.         ld a,e          ;end of file?
  1281.         or a
  1282.         ret nz          ;if not, return with Carry not set
  1283.         scf             ;else set Carry
  1284.         ret             ;and return
  1285.         ENDIF
  1286.  
  1287.  
  1288.                
  1289. delfil:
  1290.         IF CPM
  1291.         ld de,fcb
  1292. delf2:
  1293.         push de
  1294.         push hl
  1295.         ld hl,12
  1296.         add hl,de
  1297.         ld (hl),0
  1298.         ld c,delete
  1299.         call bdos
  1300.         pop hl
  1301.         pop de
  1302.         ret
  1303.         ENDIF
  1304.  
  1305.  
  1306. create: ld de,fcb
  1307. create2:
  1308.         push hl
  1309.         push de
  1310.         ld hl,12
  1311.         add hl,de
  1312.         ld (hl),0
  1313.         ld c,makfil
  1314.         call bdos
  1315.         pop de
  1316.  
  1317.         ld hl,32
  1318.         add hl,de
  1319.         ld (hl),0
  1320.         pop hl
  1321.  
  1322.         cp 255
  1323.         ret nz
  1324.  
  1325.         ld de,s6
  1326.         call pstg
  1327.         jp errab
  1328.  
  1329. ;
  1330. ; Write out the CRL file to disk:
  1331. ;
  1332.  
  1333. writf:  ld hl,fcb+9     ;make the extension "CRL"
  1334.         ld (hl),'C'
  1335.         inc hl
  1336.         ld (hl),'R'
  1337.         inc hl
  1338.         ld (hl),'L'
  1339.         call delfil     ;delete old versions
  1340.         call create     ;create new output file
  1341.  
  1342. ;       call fopen      ;open it under CP/M; under MARC, already open...
  1343.  
  1344.         lhld codp
  1345.         ex de,hl
  1346.         lhld cdao
  1347.         add hl,de
  1348.         ex de,hl
  1349.         lhld dirp
  1350.         ld (hl),80h
  1351.         inc hl
  1352.         ld (hl),e
  1353.         inc hl
  1354.         ld (hl),d
  1355.         ld hl,direc     ;write out CRL directory
  1356.  
  1357.         IF CPM
  1358.         call copys      ;(copy and write 4 sectors under CP/M)
  1359.         call writs
  1360.         call copys
  1361.         call writs
  1362.         call copys
  1363.         call writs
  1364.         call copys
  1365.         call writs
  1366.         ENDIF
  1367.  
  1368.         IF NOT CPM
  1369.         ld de,512       ;just write it all out under MARC (yey)
  1370.         call writs
  1371.         ENDIF
  1372.  
  1373.         lhld start      ;now write out the code
  1374.  
  1375.         IF CPM
  1376. writ2:  call copys
  1377.         push af
  1378.         call writs
  1379.         pop af
  1380.         jp nc,writ2
  1381.         call fclose
  1382.         ld hl,fcb+10
  1383.         ld (hl),'C'     ;delete the CCI file, if it exists
  1384.         inc hl
  1385.         ld (hl),'I'
  1386.         ENDIF
  1387.  
  1388.  
  1389.         IF NOT CPM
  1390.         call cmh
  1391.         ex de,hl
  1392.         lhld eofad
  1393.         add hl,de
  1394.         inc hl          ;HL is length of file to write out
  1395.         ex de,hl
  1396.         lhld start
  1397.         call writs      ;write out the CRL file in one shot (yey for MARC)
  1398.         call fclose
  1399.         ENDIF
  1400.  
  1401.         lda chainf
  1402.         or a            ;only attempt to delete if not chained
  1403.         call z,delfil   ;       to from CC1.
  1404.         ret
  1405.  
  1406. ;
  1407. ; Copy 128 bytes from mem at HL to tbuff:
  1408. ;       (Return C set on EOF)
  1409. ;
  1410.  
  1411.         IF CPM          ;only need this under CP/M
  1412. copys:  ld de,tbuff
  1413.         ld b,80h
  1414. copy1:  ld a,(hl)
  1415.         ld (de),a
  1416.         push de
  1417.         ex de,hl
  1418.         lhld eofad
  1419.         ld a,h
  1420.         cp d
  1421.         jp nz,copy2
  1422.         ld a,l
  1423.         cp e
  1424.         jp z,copy5
  1425. copy2:  ex de,hl
  1426.         pop de
  1427.         inc hl
  1428.         inc de
  1429.         dec b
  1430.         jp nz,copy1
  1431.         xor a
  1432.         ret
  1433.  
  1434. copy5:  pop de
  1435. copy5a: dec b
  1436.         jp z,copy7
  1437.         inc de
  1438.         ld a,1ah
  1439.         ld (de),a
  1440.         jp copy5a
  1441.  
  1442. copy7:  scf
  1443.         ret
  1444.         ENDIF
  1445.  
  1446.         IF MARC ;put this here so if the name overshoots, it'll
  1447. endnmp: ds 2            ;temporaries used in file renaming routine
  1448. dotflg: ds 1
  1449. nambuf: ds 40   ;just write into something we don't need...
  1450.         ENDIF
  1451.  
  1452. ;
  1453. ; This routine sees if anything has been typed at the console,
  1454. ; and if so, if it is a ^C then the compilation is aborted:
  1455. ;TODO
  1456.  
  1457. ckabrt: push hl
  1458.         push de
  1459.         push bc
  1460.         push af
  1461.        
  1462.         ;IF CPM
  1463.         ;lda conpol     ;if not polling console, don't so it.
  1464.         ;or a
  1465.         ;jp z,noabrt
  1466.         ;ld c,intcon
  1467.         ;call bdos
  1468.         ;or a
  1469.         ;jp z,noabrt
  1470.         ;ld c,coninp
  1471.         ;call bdos
  1472.         ;cp 3
  1473.         ;jp nz,noabrt
  1474.  
  1475.         ;ld de,stgabo
  1476.         ;call pstg
  1477.         ;jp errab      
  1478.         ;ENDIF
  1479.  
  1480.         IF NOT CPM
  1481.         ;ld c,m$ichec
  1482.         ;call msys
  1483.         ENDIF
  1484.  
  1485. noabrt: pop af
  1486.         pop bc
  1487.         pop de
  1488.         pop hl
  1489.         ret
  1490.  
  1491.         ;IF LASM
  1492.         ;link cc2b
  1493.         ;ENDIF
  1494.