?login_element?

Subversion Repositories NedoOS

Rev

Rev 632 | Blame | Compare with Previous | Last modification | View Log | Download | RSS feed

  1.  
  2. ;
  3. ; cc2b.asm:
  4. ;
  5. ; Expression evaluator (code generator)
  6. ;  The text pointer is always assumed to be in HL
  7. ;  when evaluating expressions...
  8. ;
  9. ; Note that several of the high-level routines have
  10. ;  several entry points, some of which "force a value
  11. ;  result" (if the name ends with "v") and some that don't.
  12. ;  This is to allow optimization for expressions which don't
  13. ;  really need to produce a value; for example, the statement:
  14. ;               foo++;
  15. ;  obviously doesn't need to produce a result that was the old
  16. ;  value of foo, as if it were being used in a larger expression.
  17. ;  Thus, whenever possible, we try to detect stuff like this and
  18. ;  avoid needless code generation by using the appropriate entry
  19. ;  point within the expression evaluation routines.
  20.  
  21. ;
  22. ; Top level expression evaluation entry point. Called
  23. ; from expression-statement processor only (never need return
  24. ; value when expression is entire statement):
  25. ;
  26.  
  27. exprnv: xor a
  28.         sta val         ;allow optimizing for no ret val
  29.         jp expr0
  30.  
  31. ;
  32. ; General expression evaluator entry point from outside
  33. ; itself (i.e from within the statement processor as opposed to
  34. ;         from within expr itself):
  35. ;  Note that we might need a value here, if for example this
  36. ;  gets called from the "if" statement processor...
  37. ;
  38.  
  39. expr:   call ckabrt     ;check for abortion of complilation
  40.         ld a,1
  41.         sta val         ;we want a resulting value
  42. expr0: 
  43.         push hl         ;save current line count for general error diagnosis
  44.         lhld nlcnt
  45.         shld savnlc
  46.         pop hl
  47.  
  48.         call opsin      ;initialize operator stack
  49.         xor a
  50.         sta faflg       ;clear func-arg flag
  51.         sta lflg        ;clear logical-expr flag
  52.         call expr1      ;evaluate
  53.         call igsht      ;skip trailing gunk (white space)
  54.         ret
  55.  
  56. ;
  57. ; Recursive entry point. Handles:
  58. ;       expr
  59. ;       expr,expr (except when in fun arg list or 3rd ?: expr)
  60. ;
  61. ;       Upon entry, register A tells what we want:
  62. ;               00 = rvalue
  63. ;               01 = lvalue if possible
  64. ;               02 = must have lvalue
  65. ;       (this convention remains active down to many of the
  66. ;        lower level routines also...)
  67.  
  68. ;
  69. ; Special entry point to force value result:
  70. ;
  71.  
  72. expr1v: ld b,a          ;save old A value
  73.         lda val         ;and old val value
  74.         push af
  75.         or 01h          ;force value result
  76.         sta val
  77.         ld a,b          ;restore A value
  78.         call expr1      ;evaluate
  79.         ld b,a          ;save next char of text
  80.         pop af          ;restore old val value
  81.         sta val
  82.         ld a,b          ;get back next char of text
  83.         ret             ;and done
  84.  
  85. ;
  86. ; Normal entry point:
  87. ;
  88.  
  89. expr1:  push af
  90.  
  91. exp1a:  call expr2      ;process expression
  92.         lda faflg       ;in arg list?
  93.         or a            ;if so, don't recognize comma operator
  94.         jp nz,exp1b
  95.                         ;process comma operator:
  96.         call igsht      ;no. check for , operator
  97.         cp comma
  98.         jp nz,exp1ay    ;if none, go on
  99.                         ;else process rest of comma expression:
  100.         inc hl          ;pass over the comma
  101.         call rpshp      ;reset push-op not to conflict with info from
  102.         pop af          ;get back result-type-needed flag     \first sub-expr
  103.         push af
  104.         call expr1      ;call recursively to handle rest of comma expr
  105.         call ppshp      ;restore push-opt table
  106.  
  107. exp1ay: call asgnop     ;check for assignment operator (covers hole
  108.         jp nz,exp1b     ;       in expr syntax parser)
  109.         ld de,stg8b
  110.         jp perrab
  111.  
  112. exp1b:  pop af
  113.         ret
  114.  
  115. ;
  116. ; Secondary entry point...
  117. ; Handles:
  118. ;       expr
  119. ;       expr ? expr : expr
  120. ;
  121.  
  122. ;
  123. ; Call this if we must generate a value
  124. ;
  125.  
  126. expr2v: ld b,a
  127.         lda val
  128.         push af
  129.         or 01h          ;force value result
  130.         sta val
  131.         ld a,b
  132.         call expr2
  133.         ld b,a
  134.         pop af
  135.         sta val
  136.         ld a,b
  137.         ret
  138.  
  139. ;
  140. ; Or call this if we don't care
  141. ;
  142.  
  143. expr2:  push af
  144.         call pxpr3      ;peek past binary expression
  145.         cp qmark        ;?: expression?
  146.         jp nz,expr2a
  147.         call ltabmp     ;yes, bump logical branch table
  148.         call expr3
  149.         jp qexpr        ;and go finish up in ?: handler
  150.  
  151. expr2a: pop af
  152.         push af
  153.         call expr3
  154.         pop af          ;else done
  155.         ret
  156.  
  157. ;
  158. ; Little kludge routine to pass over simple and/or binary expressions:
  159. ;
  160.  
  161. pxpr3:  push hl         ;save text ptr and line count
  162.         lhld nlcnt
  163.         ex (sp),hl
  164.         push hl
  165. pxpr3a: call sexpas     ;pass by simple expression
  166.         call binop      ;followed by binop?
  167.         jp z,morpp3
  168.         call igsht      ;make sure we get next char in A
  169.         pop hl          ;no--all done
  170.         ex (sp),hl              ;restore text ptr and line count
  171.         shld nlcnt
  172.         pop hl
  173.         ret
  174.  
  175. morpp3: inc hl          ;yes--pass it and keep scanning
  176.         jp pxpr3a
  177.  
  178.  
  179. ;
  180. ; Handles:
  181. ;       sexpr binop sexpr
  182. ;       sexpr asgnop sexpr
  183. ;       sexpr
  184. ;
  185. ;       Note: "sexpr" means "simple expression", defined here as
  186. ;             an expression having no binary, assignment, or ternary
  187. ;             operators at the top level (although it may have them
  188. ;             within parentheses)      
  189.  
  190. expr3:  push af
  191.         call sexpasl    ;peek at token past simple expr
  192.         jp nc,expr3b    ;carry from sexpasl indicates illegal
  193.         pop af          ;  simple expression: error.
  194.         ret
  195.  
  196. expr3b:
  197.         call binop      ;binary operator?
  198.         jp z,bexpr      ;if so, go handle binary expression
  199.         call asgnop     ;assignment operator?
  200.         jp nc,aexpr     ;if so, go handle assignment expression
  201.         cp qmark        ; ?-: expr?
  202.         jp nz,expr3a
  203.         pop af          ;yes. don't care if lvalue wanted
  204.         lda val
  205.         push af ;save old val
  206.         ld a,1          ;force value result, but don't force flag
  207.         sta val         ;   result to be converted to hard value
  208.         xor a           ;force rvalue of first expr
  209.         call sgenv
  210.         pop af
  211.         sta val         ;restore val
  212.         ret
  213.  
  214. expr3a: pop af          ;not ?: expr.
  215.         call sgen       ;evaluate simple expression
  216.         ret
  217.  
  218. sexpasl: push hl                ;peek past sexpr to see next
  219.         lhld nlcnt      ;non-white-space character
  220.         ex (sp),hl
  221.         push hl
  222.         call sexpas
  223.         pop hl
  224.         ex (sp),hl
  225.         shld nlcnt
  226.         pop hl
  227.         ret
  228.  
  229.  
  230. ;
  231. ; Process simple (non-binary operator involved) expression
  232. ; of form:
  233. ;       * sexpr
  234. ;       & sexpr
  235. ;       - sexpr
  236. ;       ! sexpr
  237. ;       ~ sexpr
  238. ;       sizeof expr
  239. ;       pexpr   (primary expression)
  240. ;
  241.  
  242. ;
  243. ; Recursive entry point to force value result:
  244. ;
  245.  
  246. sgenv:  ld b,a
  247.         lda val
  248.         push af
  249.         or 01h
  250.         sta val
  251.         ld a,b
  252.         call sgen
  253.         ld b,a
  254.         pop af
  255.         sta val
  256.         ld a,b
  257.         ret
  258.  
  259. ;
  260. ; Normal entry point:
  261. ;
  262.  
  263. sgen:   call sgen0
  264.         call igsht
  265.         ret
  266.  
  267. sgen0:  push af
  268.         shld cdp        ;update code buffer pointer
  269.  
  270.         xor a
  271.         sta klujf       ;clear short-cut-fetch-kludge flag
  272.  
  273.         call igsht      ;check for unary ops
  274.         cp mulcd        ;indirection operator?
  275.         jp nz,sgen3
  276.         inc hl
  277.         xor a
  278.         call rpshp
  279.         call sgenv      ;yes. evaluate operand.
  280.         call ppshp
  281.         xor a
  282.         sta value
  283.         pop af
  284.         push af
  285.         or a            ;need an address?
  286.         jp nz,sgen2     ;if so, don't gen indirection
  287.         call t2dim      ;else do. 2-dim array?
  288.         jp z,sgen2a     ;if so, generate no code
  289.         call tptrf
  290.         jp z,sgen2a     ;same for ptr to func
  291.         call tsptr      ;simple ptr?
  292.         jp z,sgen0a     ;if so, go handle indirection
  293.         call flshh1
  294.         call maca0c     ;else get value of ptr to ptr
  295.         jp sgen2a       ;and do internal indirection once only
  296.  
  297. maca0c: push af
  298.         lda optimf      ;optimizing mem indirection?
  299.         and 4
  300.         jp z,maca0e
  301.         ld a,0dfh       ;rst3: ld a,(hl);inc hl;ld h,(hl);ld l,a;ret
  302.         call genb
  303. maca0d: pop af
  304.         ret
  305. maca0e: ld de,maca0
  306.         call mcrog
  307.         pop af
  308.         ret
  309.  
  310. sgen0a: lda typ1        ;ptr to struct?
  311.         and 7
  312.         cp 6
  313.         jp z,sgen2a     ;if so, no code
  314. sgen2:  call indir      ;do internal indirection on data type
  315.         ld a,1          ;force a val result, so code such as: "*foo;" by itself
  316.         sta val         ;used to clear a memory-mapped status port, works.
  317.         jp sgen8        ;and wrap-up.
  318.  
  319. sgen2a: call indir
  320.         pop af
  321.         ret
  322.  
  323. sgen3:  cp ancd ;address-of operator?
  324.         jp nz,sgen4
  325.         ld a,2          ;if so, get address of operand
  326.         inc hl          ;now HL -> operand
  327.         call rpshp
  328.         call sgenv      ;evaluate
  329.         call ppshp
  330.         call tptrf      ;ptr to func?
  331.         jp z,sgen3b     ;if so, obscure.
  332.         call tstar      ;array?
  333.         jp z,sgen3b     ;if so, we can't represent it. just smirk.
  334.         lda indc1       ;else bump indirection count
  335.         inc a
  336.         sta indc1
  337. sgen3b: pop af          ;we don't care what was asked for here.
  338.         ret
  339.  
  340. sgen4:  cp mincd        ;minus operator?
  341.         jp nz,sgen5
  342.         inc hl
  343.         xor a
  344.         call rpshp
  345.         call sgenv      ;yes. eval argument
  346.         call ppshp
  347.         pop af
  348.         call ckvok      ;make sure we don't need lvalue
  349.         call tcnst1
  350.         jp nz,sgen4a    ;constant?
  351.         push hl         ;yes...
  352.         lhld svv1
  353.         call cmh
  354.         shld svv1
  355.         pop hl
  356.         ret
  357.  
  358. sgen4a: call flshh1
  359.         call tschr      ;simple char value to negate?
  360.         ld de,mac0e
  361.         jp nz,mcrog     ;if not, assume a 2 byte value
  362.         ld de,mac01     ;else character. turn into "int"
  363.         ld a,1
  364.         sta typ1
  365.         jp mcrog        ;and negate.
  366.  
  367. sgen5:  cp notcd        ;logical negation?
  368.         jp nz,sgen6
  369.  
  370.         pop bc          ;get saved value code
  371.         lda notklg      ;save notkludge
  372.         push af
  373.         push bc         ;and push saved value code back on stack
  374.  
  375.         xor a
  376.         sta notklg      ;by default, no notkludge is to be performed
  377.  
  378.         inc hl          ;bump txt ptr to arg of !
  379.         call igsht      ;check for "(" for a special case...
  380.         cp open
  381.         jp nz,sgen5z    ;if not, go handle normally
  382.         lda val
  383.         or a
  384.         jp p,sgen5z     ;if don't need value, also go handle normally
  385.         ld a,81h
  386. ;       sta val         ;turn into high force factor ;???why comment out???
  387.         sta notklg      ;set "notkludge" flag
  388.  
  389. sgen5z: lda val         ;get result-type-needed flag
  390.         cp 81h          ;if we need a value, then make sure we don't jump
  391.         call z,ltabmp   ; out of range of the following expression
  392.  
  393.         call ltbflp     ;flip ltab label entries and used bit bits. (No effect
  394.                         ;if a value is needed, since both T & F addrs are same)
  395.         xor a
  396.         call rpshp
  397.         call sgenv
  398.         call ppshp
  399.         call ltbflp     ;flip ltab entries back to normal (if val is false)
  400.         call ckaok      ;make sure arg is val or ptr
  401.  
  402.         lda val
  403.         cp 81h          ;was a value needed?
  404.         jp nz,sgen50    ;if not, don't clean up the range restriction
  405.         call ltabtd     ;otherwise clean up possible jump references
  406.         call ltabfd
  407.         call ltabpp
  408.  
  409. sgen50: pop af
  410.         call ckvok      ;details, details.
  411.  
  412.         call tcnst1     ;was expr a constant?
  413.         jp nz,sgen5a
  414.         push hl         ;yes. invert the logic.
  415.         lhld svv1
  416.         ld a,h
  417.         or l
  418.         jp z,sgn50a
  419.         ld hl,-1
  420. sgn50a: inc hl
  421.         shld svv1
  422.         pop hl
  423.         pop af          ;restore notkluge
  424.         sta notklg
  425.         ret
  426.  
  427. sgen5a: lda notklg      ;was notkludge flag set?
  428.         or a
  429.         jp z,sgen5y    
  430.                         ;OK--now we have to explicitly force into HL the value
  431.                         ;that resulted from the expression...
  432.         pop af
  433.         sta notklg      ;first restore the kludge flag
  434.  
  435.         lda sval1       ;result a flag setting?
  436.         and 4
  437.         jp nz,sgn5ba    ;if so, make sure not to flush it!
  438.  
  439.         jp sgen5b       ;otherwise don't skip the flushing business.
  440.  
  441. sgen5y: pop af          ;restore old notkludge flag
  442.         sta notklg
  443.  
  444.         lda sval1       ;was result of expr a flag being set?
  445.         and 4  
  446.         jp z,sgen5b
  447.  
  448.         lda sbmap1      ;yes. simply invert the logic of the flag setting
  449.         xor 1
  450.         sta sbmap1
  451.         lda val         ;absolutely need value?
  452.         cp 81h
  453.         ret nz
  454.         lda sval1       ;if so, make sure we convert current flag setting
  455.         and 0dfh        ;into an absolute value
  456.         sta sval1
  457.         call cvtlvh
  458.         ret
  459.  
  460. sgen5b:
  461.         call flshh1
  462. sgn5ba: call tschr      ;character argument?
  463.         ld de,mcn11     ;"ld a,l - or a"
  464.         jp nz,sgen5c
  465.         lda typ1        ;if so, make into int
  466.         inc a
  467.         sta typ1
  468.         jp sgen5d
  469. sgen5c: ld de,mcn10     ;else int.
  470. sgen5d: call mcrog
  471.         lda sval1       ;tell that flag is now set
  472.         or 4
  473.         sta sval1
  474.         xor a           ;flags: Z true
  475.         sta sbmap1
  476.         lda val         ;need a REAL value in HL?
  477.         or a
  478.         ret p           ;if not, all done.
  479.         ld de,macf1     ;else gen call to routine to set HL to 1 if
  480.         call mcrog      ;Z is true
  481.         lda sval1
  482.         or 20h          ;tell that value is in HL as well as in flags
  483.         sta sval1
  484.         ld a,1
  485.         sta typ1
  486.         ret
  487.  
  488. ltbflp: push hl         ;hack routine to flip the true and false ltab
  489.         push bc         ;entries, so that the not operator is real efficient
  490.         lhld ltabp
  491.         ld de,-5
  492.         add hl,de               ;get HL pointing to start of current ltab entry
  493.         ld e,(hl)               ;get true entry in DE
  494.         inc hl
  495.         ld d,(hl)
  496.         inc hl
  497.         push de         ;save it on stack
  498.         ld e,(hl)               ;get false entry in DE
  499.         inc hl
  500.         ld d,(hl)
  501.         inc hl
  502.         ld a,(hl)               ;get flag byte
  503.         call flpa       ;flip bits 0 and 7 of flag byte
  504.         ld (hl),a               ;save it back
  505.         dec hl
  506.         pop bc          ;put back true entry where false entry was
  507.         ld (hl),b
  508.         dec hl
  509.         ld (hl),c
  510.         dec hl
  511.         ld (hl),d               ;and put back false entry where true entry was
  512.         dec hl
  513.         ld (hl),e
  514.         pop bc
  515.         pop hl
  516.         ret
  517. ;
  518. ; Switch bits 0 and 7 of the value in A:
  519. ;
  520.  
  521. flpa:   ld b,0
  522.         or a            ;is bit 7 on?
  523.         jp p,flpa2
  524.         inc b
  525. flpa2:  and 1           ;is bit 0 on?
  526.         ld a,b
  527.         ret z           ;if not, return with b7 of result off also
  528.         or 80h          ;else turn on b7 of result
  529.         ret
  530.  
  531. sgen6:  cp circum       ;bitwise negate?
  532.         jp nz,sgen7
  533.         inc hl
  534.         xor a
  535.         call rpshp
  536.         call sgenv
  537.         call ppshp
  538.         call ckval      ;you get this all by now, right?
  539.         pop af
  540.         call ckvok
  541.         call tcnst1
  542.         jp nz,sgen6a
  543.         push hl
  544.         lhld svv1
  545.         call cmh
  546.         dec hl
  547.         shld svv1
  548.         pop hl
  549.         ret
  550.  
  551. sgen6a: call flshh1
  552.         call tschr
  553.         ld de,mac1b
  554.         jp nz,mcrog
  555.         ld de,mac1a
  556.         jp mcrog        ;was 'jp sgen5a'...why? ;???
  557.  
  558. sgen7:  cp sizcd        ;sizeof?
  559.         jp nz,sgen7b
  560.         pop af          ;clean up stack
  561.         inc hl
  562.         lda codflg
  563.         push af
  564.         xor a
  565.         sta codflg      ;don't generate any code while doing this
  566.         ld a,1          ;get lvalue if possible
  567.         call sgenv
  568.         pop af
  569.         sta codflg      ;restore code generation flag
  570.         push hl
  571.         call analyz     ;set asize equal to size of object
  572.         lhld asize
  573.         call tptr       ; was it a pointer?
  574.         jp nz,sgen7a
  575.         ld hl,2         ;if so, size is always gonna be 2 bytes
  576. sgen7a: shld sr0
  577.         shld svv1
  578.         ld hl,100h      ;set indc1 to 0 and typ1 to 1
  579.         shld indc1
  580.         dec h
  581.         shld dimsz1     ;and zero dim size
  582.         pop hl
  583.         ld a,1
  584.         sta sval1       ;make result a constant
  585.         ret
  586.        
  587. sgen7b: pop af          ;well... no unary operator. must be
  588.         push af ;just a plain ole' primary expr
  589.         call rpshp
  590.         call primg      ;evaluate it
  591.         call ppshp
  592.  
  593. sgen8:  pop af          ;need address?
  594.         cp 2
  595.         jp nz,sgen8a
  596.         call analyz     ;yes. Let's see if we got one...
  597.         lda aadrf
  598.         or a
  599.         ret nz          ;if so, all ok.
  600.         ld de,stg8      ;else look out!
  601.         jp perr
  602.  
  603. sgen8a: ld b,a          ;address not mandatory.
  604.         lda val         ;need we bother with value?
  605.         and 1
  606.         ret z           ;if not, we don't.
  607.         lda value       ;pre-processed value?
  608.         or a
  609.         ret nz          ;if so, leave it alone
  610.         call tsval      ;else...simple value?
  611.         ret z           ;if so, fine.
  612.         ld a,b
  613.         dec a           ;else, is an lvalue OK?
  614.         ret z           ;if so, done
  615.         call tsptr      ;simple pointer?
  616.         jp z,sgen8c     ;if so, OK.
  617.         call tstar      ;array?
  618.         jp z,sgen8c     ;that's OK too.
  619.         call tsstr      ;structure?
  620.         ret z           ;if so, just grin and bear it {It MIGHT
  621.                         ; be something like (foo).bar}
  622.                         ;is it a function? (i.e., a function name
  623.         call tfun       ;without being a call or having addr taken?)
  624.         ret z           ;if so, leave it alone.
  625.  
  626. sgen8c: call tptrf      ;ptr to func?
  627.         jp z,sgen8g
  628.  
  629.         call tstar      ;array?
  630.         jp nz,sgen8d
  631.  
  632.         lda frml1       ;yes. formal array?
  633.         or a
  634.         ret z           ;if not, all done.
  635.         xor a           ;else make it NOT formal
  636.         sta frml1       ;and indirect to get real base addr
  637.         jp sgen8g
  638.  
  639. sgen8d: call tptr       ;pointer?
  640.         jp z,sgen8g     ;if so, 2 byte indirect
  641.  
  642.         xor a           ;else must be simple lvalue.
  643.         sta indc1       ;make it an rvalue
  644.         call tschr      ;char?
  645.         jp nz,sgen8g    ;if not, do full 2 byte indirection
  646.  
  647. ;
  648. ; handle a character lvalue indirection:
  649. ;
  650.  
  651.         lda sval1       ;external char?
  652.         and 8
  653.         jp z,sgn8d4     ;if not, don't bother with kluge-fetch
  654.  
  655.         lda sval1       ;yes.
  656.         and 1           ;abs lvalue?
  657.         jp z,sgn8d3     ;if not, go do call hack
  658.  
  659. sgn8d9: ld de,mac40     ;yes. do lhld sr0, even tho we only need a char
  660.         push hl         ;get address, stick in sr0
  661.         lhld svv1
  662.         shld sr0
  663.         pop hl
  664.         call mcrog
  665.         xor a
  666.         sta sval1
  667.         ret
  668.  
  669.  
  670. sgn8d3: lda optimf      ;optimize for space?
  671.         or a
  672.         jp z,sgn8d4     ;if not, go do normal speed optimization
  673.  
  674.         lda sval1       ;do we have a const lvalue to do it on?
  675.         and 3
  676.         jp nz,sgn8d5    ;if so, go do it
  677.  
  678.                         ;no.
  679. sgn8d4: call flshh1     ;generate address of char, the hard way
  680.         ld a,6eh        ;do an indirection
  681.         call genb
  682.         xor a
  683.         sta sval1       ;all done
  684.         ret
  685.  
  686. sgn8d5: lda svv1+1
  687.         or a
  688.         jp nz,sgn8d7   
  689.         ld de,ssei
  690. sgn8d6: ld a,0cdh
  691.         call genb
  692.         call addccc
  693.         call gende
  694.         jp sgen8j
  695.  
  696. sgn8d7: ld de,lsei
  697.         jp sgn8d6
  698.  
  699. sgn8d8: call genb
  700.         jp sgen8j      
  701.  
  702.  
  703. ;
  704. ; Handle 16 bit lvalue indirection:
  705. ;
  706.  
  707. sgen8g: lda sval1       ;if we have abs external object, always use lhld
  708.         and 1
  709.         jp nz,sgn8d9
  710.  
  711.         lda optimf      ;not abs external; ok to do c.ccc fetch optimization?
  712.         or a
  713.         jp z,sgn8g0     ;if so, go deal with it
  714.  
  715.         lda sval1       ;ok to optimize for space, if an lvalue const
  716.         and 3           ;is it an lvalue constant?
  717.         jp nz,sgn8g1    ;if not, go do the hard way
  718.  
  719. sgn8g0: call flshh1     ;else get address the hard way
  720.         call maca0c     ;and do hard indirection
  721.         ret
  722.  
  723. sgn8g1: lda sval1       ;external variable?
  724.         and 8
  725.         jp z,sgn8g3
  726.  
  727.         lda svv1+1
  728.         or a
  729.         jp nz,sgn8g2
  730.  
  731.         ld de,sdei
  732.         jp sgn8d6
  733.  
  734. sgn8g2: ld de,ldei
  735.         jp sgn8d6
  736.  
  737. sgn8g3: lda svv1+1      ;short or long displacement?
  738.         or a
  739.         jp z,sgn8g4
  740.         ld de,ldli
  741.         lda optimf
  742.         and 20h
  743.         jp z,sgn8d6
  744.         ld a,0f7h       ;rst 6: jp ldli
  745.         jp sgn8d8
  746.  
  747. sgn8g4: ld de,sdli
  748.         lda optimf
  749.         and 10h
  750.         jp z,sgn8d6
  751.         ld a,0efh       ;rst 5: jp sdli
  752.         jp sgn8d8
  753.  
  754.  
  755. sgen8j: lda svv1        ;now generate displacement.
  756.         call genb       ;always do low order byte.
  757.         lda svv1+1      ;but do high-order only if non-zero.
  758.         or a
  759.         call nz,genb
  760.         xor a
  761.         sta sval1
  762.         ret
  763.  
  764.  
  765. gende:  push de         ;generate code equal to DE:    
  766.         ld a,e 
  767.         call genb
  768.         pop de
  769.         ld a,d
  770.         call genb
  771.         ret
  772.  
  773.        
  774. addccc: push hl
  775.         lhld cccadr
  776.         add hl,de
  777.         ex de,hl
  778.         pop hl
  779.         ret
  780.  
  781.  
  782. ;
  783. ; Evaluate primary expression of form:
  784. ;       ++pexpr
  785. ;       --pexpr
  786. ;       pexpr++
  787. ;       pexpr--
  788. ;       pexpr[expr]
  789. ;       pexpr(arg list opt)
  790. ;       pexpr.identifier
  791. ;       pexpr->identifier
  792. ;       spexpr  (i.e, simple primary expr)
  793. ;
  794. ;  Note that whenever possible, this routine generates the
  795. ;  address of the object. Only special cases like constants
  796. ;  and functions may evaluate to constant values.
  797. ;
  798.  
  799. primg:  ld c,a
  800.         xor a
  801.         sta value       ;clear pre-processed-value flag
  802.         sta indc1
  803.         sta frml1
  804.         sta klujf
  805.         sta sbmap1
  806.         xor a
  807.         sta sval1
  808.         push hl
  809.         ld hl,0
  810.         shld svv1
  811.         shld dimsz1     ;clear array size
  812.         pop hl
  813.         call igsht
  814.         cp pplus        ;leading ++ ?
  815.         ld b,0
  816.         jp z,prmg2a
  817. primg2: cp mmin ;leading -- ?
  818.         jp nz,primg3
  819.         ld b,2          ;yes.
  820. prmg2a: push bc
  821.         inc hl
  822.         ld a,2
  823.         call sgenv      ;evaluate the lvalue
  824.         pop bc 
  825.         call tsclv      ;if character lvalue,
  826.         jp z,prmg2b     ;  always get address into HL before doing ++ or --
  827.         lda sval1      
  828.         and 1
  829.         jp nz,prim30    ;if abs external lvalue, DON'T flush addr into HL
  830.        
  831. prmg2b: call flshh1     ;flush to get lvalue in HL if not abs external non-char
  832.         jp prim30       ;and perform the ++ or -- operation
  833.  
  834. primg3: call sprimg     ;process simple primary expr
  835. primg4: call igsht      ;check for primary expr op
  836.         cp open ;function call?
  837.         jp z,primf
  838.         cp openb        ;subscripting?
  839.         jp z,primb
  840.         cp period       ; . ?
  841.         jp z,primp
  842.         cp arrow        ; -> ?
  843.         jp z,prima
  844. primg6: call igsht
  845.         cp pplus        ;trailing ++ ?
  846.         jp nz,primg7
  847.         ld b,1
  848.         jp primg8
  849.  
  850. primg7: cp mmin ;trailing -- ?
  851.         jp z,prmg7a
  852.  
  853.         cp varcd        ;primary expression followed by a name? if not,
  854.         ret nz          ;all done with this primary expression.
  855.        
  856.         ld de,s4        ;probably a missing semicolon
  857.         call perrsv
  858.         ret
  859.        
  860. prmg7a: ld b,3
  861. primg8: inc hl
  862.         call tsclv      ;if simple character lvalue, always flush addr 
  863.         jp z,primg9
  864.         lda sval1       ;if abs external lvalue, DON'T flush
  865.         and 1
  866.         jp nz,prmg10
  867.        
  868. primg9: call flshh1     ;flush into HL for prim30
  869. prmg10: call prim30     ;yes. perform post-decrement
  870.         jp primg4
  871.  
  872.  
  873.  
  874.  
  875. ;
  876. ; Evaluate simple primary expression of form:
  877. ;       (expr)
  878. ;       string constant
  879. ;       numeric constant
  880. ;       identifier (variable name, that is)
  881. ;
  882.  
  883. sprimg: call igsht
  884.         cp open ;left parenthesis?
  885.         jp nz,sprms
  886.         ld b,c
  887.         call sprmp      ;yes. process expr in parens
  888.         call igsht
  889.         ret
  890.  
  891. ;
  892. ; Process expression in parentheses:
  893. ;
  894.  
  895. trbnop: ds 1            ;trailing-binop flag, for use by sprmp
  896.  
  897. sprmp:  lda faflg       ;save old fun-arg flag
  898.         push af
  899.         lda trbnop
  900.         push af ;save trailing binop flag
  901.         xor a
  902.         sta faflg       ;clear fun-arg flag
  903.         sta trbnop      ;clear trailing binop flag
  904.         lda val
  905.         push af
  906.         push hl         ;peek after (), looking for a primop
  907.         lhld nlcnt
  908.         ex (sp),hl
  909.         push hl
  910.         call mtchp
  911.         call igsht
  912.         cp pplus
  913.         jp z,sprmp2
  914.         cp mmin
  915.         jp nz,sprmp3
  916. sprmp2: lda val         ;we found a ++ or --; force lvalue result
  917.         or 1            ;and thus force value result
  918.         sta val
  919.         ld a,2
  920.         jp sprmp6
  921.  
  922. sprmp3: push bc
  923.         call binop      ;() followed by binary operator?
  924.         pop bc
  925.         jp nz,sprmp4
  926.         call lbinop     ;yes...if logical, don't worry about it
  927.         jp z,sprmp4
  928.         call ltabmp     ;not logical. bump ltab,
  929.         ld a,81h
  930.         sta val         ; and force value result
  931.         sta trbnop      ;set trailing binop flag (so that
  932.         ld a,b          ;restore evaluation code
  933.         jp sprmp6       ; ltab will be popped later)
  934.  
  935. sprmp4: call primop
  936.         ld a,b          ;if other primop
  937.         jp nz,sprmp6
  938.         lda val
  939.         or 1
  940.         sta val         ;force result
  941.         xor a           ;get rvalue no matter what
  942.  
  943. sprmp6: pop hl
  944.         ex (sp),hl              ;restore text pointer and line count
  945.         shld nlcnt      ;to what they were before the
  946.         ex (sp),hl              ;peek-ahead
  947.         inc hl
  948.         call expr1      ;evaluate inside of parens
  949.         pop de
  950.         pop af
  951.         sta val         ;restore old val
  952.         lda trbnop      ;trailing binop flag set?
  953.         or a
  954.         jp z,sprmp7
  955.  
  956.         call ltabtd     ;if so, define true and false ltab entries
  957.         call ltabfd
  958.         call ltabpp     ;and pop off the ltab entry
  959.  
  960. sprmp7: pop af
  961.         sta trbnop      ;restore former trailing binop flag
  962.         pop af
  963.         sta faflg       ;restore old fun arg flag
  964.         push de
  965.         call igsht
  966.         cp close        ;check for matching )
  967.         jp z,sprmp8
  968.         ex (sp),hl              ;if none, error.
  969.         push hl
  970.         lhld nlcnt
  971.         ex (sp),hl
  972.         shld nlcnt
  973.         ld de,stg9
  974.         call perr
  975.         pop hl
  976.         shld nlcnt
  977.         pop hl
  978.         call psemi
  979.         ret
  980.  
  981. sprmp8: pop de          ;wrap up
  982.         inc hl
  983.         ld a,1 
  984.         sta value
  985.         ret
  986.  
  987. ;
  988. ; If string constant, put string in-line, generate a
  989. ; pointer to it and a jump around it:
  990. ;
  991.  
  992. sprms:  cp strcd        ;string constant?
  993.         jp nz,sprmc
  994.         xor a           ;yes. make type "pointer to chars"
  995.         sta typ1
  996.         ld a,2          ;and set up other type info
  997.         sta indc1
  998.         sta value
  999.         inc hl          ;get the string code number in DE
  1000.         ld e,(hl)
  1001.         inc hl
  1002.         ld d,(hl)
  1003.         inc hl
  1004.         push hl         ;save text pointer
  1005.         lhld stgad      ;now search for the given string in the string pool
  1006. sprms1: ld c,(hl)
  1007.         inc hl
  1008.         ld b,(hl)
  1009.         inc hl
  1010.         ld a,b
  1011.         cp d
  1012.         jp nz,sprms2
  1013.         ld a,c
  1014.         cp e
  1015.         jp z,sprms3     ;found string code match?
  1016. sprms2: push de         ;no. try next string in pool
  1017.         ld e,(hl)
  1018.         ld d,0
  1019.         inc de
  1020.         add hl,de
  1021.         pop de
  1022.         jp sprms1
  1023.  
  1024. sprms3: push hl         ;found string. check for folding potential and
  1025.         call entstr     ;enter into table if a new unique string...
  1026.         pop hl
  1027.         jp c,sprms4     ;was the table out of space?
  1028.         ex de,hl                ;no. put label code for the string into HL
  1029.         shld sr0
  1030.         ld de,mac98a    ;ld hl,sr0 (with a forward reference)
  1031.         call mcrog
  1032.         pop hl          ;restore text pointer
  1033.         ret             ;all done
  1034.  
  1035. sprms4: push hl         ;generate ld hl,foo - jp bar - foo: <text>,0 - bar:
  1036.         call glbl       ;set up some symbolic labels
  1037.         shld sr0
  1038.         call glbl
  1039.         shld sr1
  1040.         ld de,mac98
  1041.         call mcrog
  1042.         pop hl
  1043.         ld b,(hl)               ;found it. B holds length; now generate the
  1044. sprms5: inc hl          ;string characters.
  1045.         ld a,b
  1046.         or a
  1047.         jp z,sprms6     ;done?
  1048.         ld a,(hl)               ;no. generate next byte
  1049.         call genb
  1050.         dec b
  1051.         jp sprms5       ;and go for more
  1052.  
  1053. sprms6: xor a           ;generate trailing null byte
  1054.         call genb
  1055.         lhld sr1        ;and define the symbolic label
  1056.         ex de,hl                ;at the end of the string (this is the object
  1057.         call entl       ;of the jump after the ld hl,string instruction
  1058.         pop hl
  1059.         ret
  1060.  
  1061. entstr: push hl         ;calculate label code for a new string
  1062.         ld hl,strtb     ;if already in table, return old code, else enter it.
  1063. ntstr0: ld e,(hl)               ;get next label # from table into DE
  1064.         inc hl
  1065.         ld d,(hl)
  1066.         inc hl
  1067.         ld a,d          ;end of table?
  1068.         or e
  1069.         jp nz,ntstr0
  1070.  
  1071.         push hl         ;yes. check to see if table is full
  1072.         push de
  1073.         call cmh        ;HL := -(table pointer)
  1074.         ld de,strtb+strsz
  1075.         add hl,de               ;calcualate (end - current_pointer)
  1076.         pop de
  1077.         ld a,h
  1078.         pop hl
  1079.         or a            ;overflow?
  1080.         jp p,ntstr1
  1081.         pop hl          ;yes.
  1082.         scf             ;return carry
  1083.         ret
  1084.  
  1085. ntstr1: ex de,hl                ;there is room for another entry
  1086.         call glbl       ;get new label code
  1087.         ex de,hl                ;put into DE
  1088.         dec hl
  1089.         ld (hl),d               ;enter label code in table
  1090.         dec hl
  1091.         ld (hl),e
  1092.         inc hl
  1093.         inc hl          ;now enter pointer to text
  1094.         pop bc          ;which was on the stack
  1095.         ld (hl),c
  1096.         inc hl
  1097.         ld (hl),b
  1098.         inc hl          ;and clear next field as end flag
  1099.         xor a
  1100.         ld (hl),a
  1101.         inc hl
  1102.         ld (hl),a
  1103.         ret             ;all done.
  1104.  
  1105.  
  1106.         IF 0            ;disable string-folding, since it isn't standard...
  1107.  
  1108. ntstr2: ld c,(hl)               ;compare current table entry with given text
  1109.         inc hl
  1110.         ld b,(hl)               ;BC :=  --> current table entry text
  1111.         inc hl
  1112.         ex (sp),hl              ;HL := new string entry being processed
  1113.         push hl         ;save the starting addr of the label
  1114.         push de         ;save the label code
  1115.         ld a,(bc)               ;check length bytes against each other
  1116.         cp m
  1117.         jp z,ntstr4     ;same length?
  1118. ntstr3: pop de          ;no, so a mismatch right off.
  1119.         pop hl
  1120.         ex (sp),hl              ;restore stuff for another try
  1121.         jp ntstr0
  1122.  
  1123. ntstr4: ld d,a          ;ok, lengths match. now compare text
  1124.         inc d           ;D holds char count
  1125. ntstr5: dec d           ;done?
  1126.         jp nz,ntstr6
  1127.         pop de          ;yes...we have a match. use old label code (in DE now)
  1128.         pop hl
  1129.         pop hl          ;restore HL
  1130.         ret             ;and done
  1131.  
  1132. ntstr6: inc bc          ;keep on comparing the two strings
  1133.         inc hl
  1134.         ld a,(bc)
  1135.         cp m
  1136.         jp z,ntstr5     ;still matching? if so, keep going.
  1137.         jp ntstr3       ;no. go on to next entry
  1138.  
  1139.         ENDIF
  1140.  
  1141.  
  1142. ;
  1143. ; If numeric constant, generate "ld hl,whatever"
  1144. ;
  1145.  
  1146. sprmc:  cp concd        ;constant?
  1147.         jp nz,sprmv
  1148.         inc hl          ;yes. get the value in DE
  1149.         ld e,(hl)
  1150.         inc hl
  1151.         ld d,(hl)
  1152.         inc hl
  1153.         ex de,hl                ;generate ld hl,value
  1154.         shld svv1
  1155.         ex de,hl
  1156.         ld a,1          ;make type integer
  1157.         sta typ1
  1158.         sta sval1       ;make it a constant
  1159.         call igsht
  1160.         ret
  1161.  
  1162. ;
  1163. ; Process an identifier. If not an identifier, error.
  1164. ;
  1165.  
  1166. sprmv:  cp varcd        ;identifier?
  1167.         jp z,sprmv2
  1168.         ld de,stg10     ;no. At this point it can't be anything
  1169.         call perrsv     ;else except an error. Find the next semicolon
  1170.         call fsemi      ;and attempt to keep going from there.
  1171.         ret
  1172.  
  1173. sprmv2: call lookup     ;look up the identifier in the symbol table.
  1174.         ex de,hl
  1175.         shld sr0        ;save displacement for later code generating use
  1176.         shld svv1
  1177.         ex de,hl                ;and leave in DE also
  1178.         lda typ1        ;is it a struct or union element?
  1179.         and 80h
  1180.         jp z,sprmv3
  1181.         ld de,stg20     ;if so, error.
  1182.         call perr
  1183. sprmv3: lda typ1        ;is it a function?
  1184.         and 40h
  1185.         jp z,sprmv5
  1186.         sta simpf       ;yes. set "simple function" (as opposed to a pointer
  1187.         lda indc1       ; to a function) flag. Then fudge the indirection
  1188.         or a            ; count if necessary.
  1189.         jp z,sprmv4
  1190.         inc a
  1191.         sta indc1
  1192. sprmv4: call igsht      ;followed by an open paren?
  1193.         cp open
  1194.         ret z           ;if so, is a simple function and may be ignored.
  1195.         push hl         ;else is not so simple.
  1196.         lhld dimsz1     ; used to generate ld hl,addr; NOW generate:
  1197.         inc hl          ;               lhld addr+1
  1198.         shld sr0
  1199.         ld hl,0
  1200.         shld dimsz1
  1201.         ld de,mac40r    ; lhld sr0 (relocated)
  1202.         call mcrog
  1203.         pop hl
  1204.         xor a           ;and reset the simple function call flag.
  1205.         sta simpf
  1206.         ret
  1207.  
  1208. sprmv5: call tptrf      ;pointer to func?
  1209.         jp z,sprv5a     ;if so, don't touch indir count
  1210.         lda indc1       ;else do.
  1211.         inc a
  1212.         sta indc1
  1213. sprv5a: ld a,2
  1214.         sta sval1
  1215.         lda vext        ;external?
  1216.         or a            ;if not, all done
  1217.         ret z
  1218.  
  1219.         ld a,0ah        ;yes; make it external and an lvalue
  1220.         sta sval1       ;set the external bit.
  1221.         lda eflag       ;absolute external mode enabled?
  1222.         or a
  1223.         ret z           ;if not, all done
  1224.  
  1225.         push hl         ;if absolute externals enabled,
  1226.         lhld exaddr     ;get the base address
  1227.         add hl,de               ;add to offset
  1228.         shld svv1       ;and make that the value
  1229.         ex de,hl                ;leave it in DE also
  1230.         pop hl
  1231.         ld a,0bh        ;now: external, an lvalue, and a constant!
  1232.         sta sval1      
  1233.         ret
  1234.  
  1235. genllv: push hl
  1236.         lhld sr0
  1237.         ld a,h
  1238.         or l
  1239.         pop hl
  1240.         jp z,genlv2
  1241.         ld de,mac41
  1242.         call mcrog
  1243.         ret
  1244.  
  1245. genlv2: ld a,60h        ;if has local displacement of zero,
  1246.         call genb       ;can skip the "ld hl,disp add hl,bc" and
  1247.         ld a,69h        ;just do a "ld h,b  ld l,c" instead.
  1248.         call genb       ;(a little optimization here, a bit there...)
  1249.         ret
  1250.  
  1251. ;
  1252. ; Process subscript expression (on entry, HL -> "[")
  1253. ;
  1254.  
  1255. primb:  call analyz     ;check for pointer base
  1256.         lda amathf      ; (weed out illegal bases)
  1257.         or a
  1258.         jp z,prmb2a
  1259.         call tstar      ;array?
  1260.         jp z,prmb1      ;if so, not pointer base.
  1261.         lda value       ;pre-processed value?
  1262.         or a
  1263.         jp nz,prmb1
  1264.         call tptr       ;no. pointer?
  1265.         jp nz,prmb1
  1266.         call indnoc
  1267. prmb1:  xor a
  1268.         sta value
  1269.         inc hl
  1270.         lda frml1
  1271.         or a
  1272.         jp z,prmb2
  1273.         call tstar
  1274.         jp nz,prmb2
  1275.         call indnoc
  1276.         xor a
  1277.         sta frml1
  1278.  
  1279. prmb2:  call tptr
  1280.         jp z,prmb3
  1281. prmb2a: ld de,stg16     ;illegal array base error
  1282.         call perr
  1283.  
  1284. prmb3:  ex de,hl
  1285.         lhld indc1
  1286.         push hl
  1287.         lhld dimsz1
  1288.         push hl
  1289.         lhld strsz1
  1290.         push hl
  1291.         lhld asize
  1292.         push hl
  1293.         lhld sval1
  1294.         push hl
  1295.         lhld svv1
  1296.         push hl
  1297.         ex de,hl
  1298.         lda faflg
  1299.         push af
  1300.         xor a
  1301.         sta faflg
  1302.         call tcnst1
  1303.         call z,rpshp
  1304.         call nz,spshp
  1305.         xor a
  1306.         call expr1v     ;evaluate subscript
  1307.         lda sval1
  1308.         sta ssval
  1309.         and 1
  1310.         call z,flshh1   ;if not constant, flush subscript
  1311.         xor a
  1312.         sta value
  1313.         pop af
  1314.         sta faflg
  1315.         xor a
  1316.         sta frml1
  1317.         call tsval
  1318.         lda typ1
  1319.         ex de,hl
  1320.         lhld svv1
  1321.         shld subval
  1322.         pop hl
  1323.         shld svv1
  1324.         pop hl
  1325.         shld sval1
  1326.         pop hl
  1327.         shld asize
  1328.         pop hl
  1329.         shld strsz1
  1330.         pop hl
  1331.         shld dimsz1
  1332.         pop hl
  1333.         shld indc1
  1334.         ex de,hl
  1335.         jp z,prmb4
  1336.         ld de,stg15
  1337.         call perr
  1338.         inc hl
  1339.         jp primg4
  1340.  
  1341. prmb4:  push hl
  1342.         push af
  1343.         lda ssval
  1344.         and 1           ;was subscript a constant?
  1345.         jp z,prmb4b
  1346.         call ppshp      ;yes.
  1347.         lda sval1       ;is base a constant too?
  1348.         and 3
  1349.         jp z,prmb4a
  1350.         lhld asize      ;yes; entire expression can be constant
  1351.         call mult
  1352.         ex de,hl
  1353.         lhld svv1
  1354.         add hl,de
  1355.         shld svv1
  1356.         pop af
  1357.         jp prmb6d
  1358.  
  1359. prmb4a: pop af
  1360.         lhld asize      ;we have const subscript, but NOT constant base
  1361.         call mult       ;entire subscrip expr can be a constant
  1362.         push hl         ;..add it to the base. 
  1363.         call flshh1     ;generate code for the base
  1364.         pop de
  1365.         call maddd      ;and code to add subscript to it
  1366.         jp prmb6c       ;and go wrap up
  1367.  
  1368. prmb4b: pop af          ;NOT constant subscript; has been flushed into HL
  1369.         or a            ;char value?
  1370.         jp nz,prmb5
  1371.         ld de,mac61     ;yes, clear H
  1372.         call mcrog
  1373.  
  1374. prmb5:  lhld asize      ;get final subscript value into HL
  1375.         call gnmulh     ;gen code to mult HL by asize
  1376.         call ppshp
  1377.         call tcnst1     ;was base a constant lvalue?
  1378.         jp z,prmbts     ;if so, go handle that scwewy case.
  1379.                         ;this stuff commented out for now; perhaps forever.
  1380.  
  1381.         call gpopd      ;gen code to pop base into DE
  1382.  
  1383. prmbad: ld a,19h        ;"add hl,de"
  1384.         call genb
  1385.  
  1386. prmb6c: xor a           ;result in HL
  1387.         sta sval1
  1388.  
  1389. prmb6d: pop hl          ;clean up.
  1390.         inc hl
  1391.         call indir
  1392.         jp primg4
  1393.  
  1394. indnoc: call flshh1
  1395.         call maca0c
  1396.         ret
  1397.  
  1398. prmbts: lhld svv1
  1399.         shld sr0
  1400.         lda sval1
  1401.         and 8
  1402.         jp nz,prbts2
  1403.         call gexdehl    ;'ex de,hl' subscript into DE
  1404.         call genllv
  1405.         jp prmbad
  1406.  
  1407. prbts2: lda sval1
  1408.         and 1
  1409.         jp z,prbts3
  1410.         ld de,mac0c
  1411.         call mcrog
  1412.         jp prmb6c
  1413.  
  1414. prbts3: ld a,h          ;save adjusted subscript on stack, unless base
  1415.         or l            ; address of array is zero...
  1416.         call nz,gpushh  ;either save adjusted subscript
  1417.         call z,gexdehl  ;or just put it in DE for a while
  1418.         ld de,mac6a
  1419.         call mcrog      ;do 'lhld extbas'
  1420.         ex de,hl                ;add relative external address to extbas
  1421.         push de
  1422.         call maddd
  1423.         pop hl
  1424.         ld a,h
  1425.         or l            ;now, if subscript was pushed on the stack,
  1426.         call nz,gpopd   ;get back adjusted subscript (else don't)
  1427.         jp prmbad       ;and go add it
  1428.  
  1429.  
  1430. ;
  1431. ; Process function call:
  1432. ;
  1433.  
  1434. primf:  call tfun       ;was thing before '(' a function?
  1435.         jp z,prmf2
  1436.         ld de,stg11     ;if not, error.
  1437.         call perr
  1438.         call mtchp
  1439.         jp primg4
  1440.  
  1441. prmf2:  xor a
  1442.         sta argcnt      ;clear arg count
  1443.         lda simpf       ;OK...is it a simple function call?
  1444.         or a
  1445.         jp z,prmf4
  1446.         call sargs      ;yes. process args
  1447.         ld de,mac08     ;generate "call" op
  1448.  
  1449. prmf3:  call mcrog
  1450.  
  1451.         lda argcnt      ;now restore stack. more than 6 args?
  1452.         cp 7
  1453.         jp c,prmf3a
  1454.  
  1455.         push hl         ;yes. use the long sequence.
  1456.         ld l,a
  1457.         ld h,0          ;HL = argcnt
  1458.         add hl,hl               ;HL = # of bytes of stack used
  1459.         shld sr0
  1460.         pop hl
  1461.         ld de,mac8ar    ;long code sequence to reset SP
  1462.         call mcrog     
  1463.         jp prmf3c
  1464.  
  1465. prmf3a: ld b,a          ;save count in B
  1466.         inc b
  1467. prmf3b: dec b
  1468.         jp z,prmf3c
  1469.         call gpopd      ;"pop de" for each arg
  1470.         jp prmf3b      
  1471.  
  1472. prmf3c: lda typ1        ;set type of returned value
  1473.         and 0bfh
  1474.         sta typ1
  1475.         ld a,1
  1476.         sta value
  1477.         call igsht
  1478.         jp primg4
  1479.  
  1480. prmf4:  call flshh1
  1481.         call gpushh     ;handle non-simple function call
  1482.                         ;gen code to push func address
  1483.         call sargs      ;process args
  1484.         lda argcnt      ;bump arg count to account for pushed func addr
  1485.         inc a           ;   later when we reset the SP after returning
  1486.         sta argcnt     
  1487.  
  1488.         push hl         ;generate code to retrieve function addr we
  1489.         ld l,a          ;pushed before processing args.
  1490.         ld h,0
  1491.         add hl,hl              
  1492.         shld sr1        ;special displacement needed by mac8a
  1493.         pop hl
  1494.  
  1495.         ld de,mac8a     ;special non-simple function call code sequence
  1496.         jp prmf3
  1497.  
  1498. ;
  1499. ; Process function argument list:
  1500. ;
  1501.  
  1502. sargs:  ex de,hl                ;save HL
  1503.         lhld dimsz1
  1504.         push hl
  1505.         lhld indc1
  1506.         push hl
  1507.         lhld strsz1
  1508.         push hl
  1509.         lhld sval1
  1510.         push hl
  1511.         lhld svv1
  1512.         push hl
  1513.         lda simpf
  1514.         push af
  1515.  
  1516.         ex de,hl                ;restore HL
  1517.  
  1518. ;
  1519. ; Now push the beginning address of the text of each function
  1520. ; argument: (# of addresses pushed will end up in argcnt)
  1521. ;
  1522.  
  1523. srgs0:  inc hl
  1524. srgs1:  call igsht
  1525.         cp close
  1526.         jp z,srgs3      ;if end of arg list, go backtrack and evaluate...
  1527.  
  1528. srgs2:  push hl         ;else another arg to push text address of.
  1529.  
  1530.         ex de,hl                ;save text ptr in DE
  1531.         lhld nlcnt      ;save the line number associated with the arg text
  1532.         push hl
  1533.         ex de,hl                ;restore text ptr
  1534.  
  1535.         push bc
  1536.         lda argcnt
  1537.         inc a
  1538.         sta argcnt
  1539.                         ;pass over an arg. This is much neater than the old
  1540.         call pasarg     ;way of disabling code generation and evaluating the
  1541.                         ;arg!
  1542.         pop bc
  1543.         call igsht
  1544.         cp comma        ;arg followed by comma?
  1545.         inc hl
  1546.         jp z,srgs2      ;if so, bump text pointer and look for more args
  1547.         dec hl          ;else look for close paren
  1548.  
  1549. srgs2a: cp close
  1550.         call nz,plerr   ;if not followed by a close paren, error
  1551.  
  1552. srgs3:  push hl
  1553.         lhld nlcnt
  1554.         shld savcnt     ;save line count for end of list
  1555.         pop hl
  1556.  
  1557. ;
  1558. ; Now, for each saved address, generate the code for
  1559. ; the argument and push it:
  1560. ;
  1561.  
  1562. srgs4:  shld savtxt     ;save text pointer to end of list
  1563.  
  1564.         lda argcnt      ;get arg count 
  1565. srgs5:  or a
  1566.         jp z,srgs6      ;done?
  1567.         push af ;save argcount
  1568.         call igsht      ;if not, we'd better be staring at a comma!
  1569.         cp comma
  1570.         jp z,srgs5a
  1571.         cp close
  1572.         call nz,plerr   ;tell about it if we aren't
  1573. srgs5a: pop af          ;get back argcount
  1574.         pop hl          ;restore the line number matching the arg
  1575.         shld nlcnt
  1576.         pop hl          ;get text of previous arg and evaluate
  1577.         push af ;save argcnt
  1578.  
  1579.         lda val
  1580.         push af ;save current state of val
  1581.         or 81h          ;force value result even for logical expressions
  1582.         sta val
  1583.         call doarg
  1584.         call igsht
  1585.         pop af
  1586.         sta val         ;restore former state of val
  1587.  
  1588.         lda sval1
  1589.         and 0c0h
  1590.         call z,gpushh   ;generate "push hl" if value in HL
  1591.         call nz,gpushd  ;else "push de" is called for
  1592.  
  1593.         pop af          ;get back argcnt
  1594.         dec a           ;de-bump
  1595.         jp srgs5        ;and go do next arg    
  1596.  
  1597. ;
  1598. ; Come here to diagnose a parameter list error:
  1599. ;
  1600.  
  1601. plerr:  ld de,stgbf     ;else must've been a parameter list error
  1602.         call perr
  1603.         call fsemi
  1604.         dec hl
  1605.         ret
  1606.  
  1607. ;
  1608. ; This routine passes over the text of a function arg--all parens,
  1609. ; brackets get matched, and first comma or close paren at upper
  1610. ; level terminates the scan.
  1611. ;
  1612.  
  1613. pasarg: call pascd2     ;ignore codes and cruft
  1614.         cp openb        ;if [,
  1615.         jp nz,pasrg2
  1616.         call mtchb      ;find matching ]
  1617.         jp pasarg       ;and go on
  1618.  
  1619. pasrg2: cp open ;if (,
  1620.         jp nz,pasrg3    ;find matching )
  1621.         call mtchp
  1622.         jp pasarg       ;and go on
  1623.  
  1624. pasrg3: cp comma        ;if comma
  1625.         ret z           ;found end
  1626.         cp close        ;same for top level )
  1627.         ret z
  1628.         call badxch     ;is character OK in an expression?
  1629.         ret c           ;return w/carry set if no good
  1630. pasrg4: inc hl          ;else scan to next character
  1631.         jp pasarg
  1632.  
  1633. ;
  1634. ; Return C set if keyword code in A is illegal within an expr:
  1635. ;
  1636.  
  1637. badxch: cp semi ;semicolon no good
  1638.         scf
  1639.         ret z
  1640.         cp sizcd        ;sizeof OK
  1641.         ret z
  1642.         cp rbrcd+2      ;if <= maincode, no good
  1643.         ret
  1644.  
  1645. ;
  1646. ; Restore everything and prepare to generate calling sequence:
  1647. ;
  1648.  
  1649. srgs6:  pop af
  1650.         sta simpf
  1651.         lhld savcnt     ;get line count for end of list
  1652.         shld nlcnt      ;restore as current count
  1653.         pop hl
  1654.         shld svv1
  1655.         pop hl
  1656.         shld sval1
  1657.         pop hl
  1658.         shld strsz1
  1659.         pop hl
  1660.         shld indc1
  1661.         pop hl
  1662.         shld sr3
  1663.         ld hl,0
  1664.         shld dimsz1
  1665.         lhld sfsiz
  1666.         shld sr0
  1667.         call glbl
  1668.         shld sr2
  1669.  
  1670.         lhld savtxt     ;get back text pointer
  1671.         inc hl
  1672.         ret
  1673.  
  1674. ;
  1675. ; Process the arg at HL, either generating code or not depending
  1676. ; on the state of codflg:
  1677. ;
  1678.  
  1679. doarg:  lda faflg       ;bump funarg flag so commas are treated
  1680.         inc a           ;as terminators instead of operators.
  1681.         sta faflg
  1682.  
  1683.         lda argcnt
  1684.         push af
  1685.  
  1686.         ex de,hl
  1687.         lhld savtxt
  1688.         push hl
  1689.         lhld savcnt
  1690.         push hl
  1691.         lhld nlcnt      ;save nlcnt of START of arg for error reports
  1692.         push hl
  1693.         ex de,hl
  1694.  
  1695.         call rpshp
  1696.         call ltabmp     ;bump ltab, to keep logical branches from escaping
  1697.         xor a           ;evaluate arg
  1698.         call expr1v
  1699.        
  1700.         call igsht      ;make sure arg is followed by comma or close paren
  1701.         cp comma
  1702.         jp z,doarg1     ;if comma, OK
  1703.         cp close
  1704.  
  1705.         ex de,hl                ;get nlcnt that was valid at START of arg, so error
  1706.         pop hl          ;report points to beginning of illegally-terminated
  1707.         shld nlcnt      ;parameter
  1708.         push hl
  1709.         ex de,hl
  1710.  
  1711.         call nz,plerr   ;if nor comma or close paren, complain
  1712.  
  1713. doarg1: call ltabfd     ;come here whether false
  1714.         call ltabtd     ;               of true
  1715.         call ltabpp     ;value results from arg expression
  1716.         call ppshp
  1717.  
  1718.         lda sval1       ;if a constant,
  1719.         and 3
  1720.         call nz,flshh1  ;flush into HL
  1721.                         ;else might be in either HL or DE
  1722.         ex de,hl                ;restore state
  1723.         pop hl          ;clean up stack (pushed nlcnt earlier)
  1724.         pop hl
  1725.         shld savcnt
  1726.         pop hl
  1727.         shld savtxt
  1728.        
  1729.         ex de,hl
  1730.  
  1731.         pop af
  1732.         sta argcnt
  1733.  
  1734.         call tschr      ;and generate code to zero high byte
  1735.         jp nz,doarg2    ;if arg is a char
  1736.         lda sval1       ;clear H if value in HL
  1737.         and 0c0h
  1738.         ld de,mac61
  1739.         call z,mcrog
  1740.         ld de,mac62     ;else clear D
  1741.         call nz,mcrog
  1742.  
  1743. doarg2: lda faflg       ;reset funarg flag to handle commas correctly
  1744.         dec a
  1745.         sta faflg
  1746.         ret
  1747.  
  1748. ;
  1749. ; Handle -> operator:
  1750. ;
  1751.  
  1752. prima:  inc hl
  1753.         call analyz
  1754.         call tptrf
  1755.         jp z,prmae      ;ptr to func no good as base
  1756.         lda amathf
  1757.         or a
  1758.         jp z,prmae      ;base no good if can't do math on it
  1759.         lda aadrf      
  1760.         or a
  1761.         jp z,prma2      ;if not an address, don't need to indirect
  1762.         lda avar
  1763.         or a
  1764.         jp z,prma0      ;if not a variable, also don't need to indirect
  1765.         call tschr      ;no characters allowed as base
  1766.         jp z,prmae
  1767.  
  1768. prma0:  call tstar      ;is the base an array?
  1769.         jp nz,prma1
  1770.         lda frml1       ;yes...a formal one?
  1771.         or a
  1772.         jp z,prma2      ;if not, don't indirect
  1773. prma1:  lda value       ;if base already a value, don't indirect
  1774.         or a
  1775.         jp nz,prma2
  1776.         call sgen8g     ;else get the value of the pointer on left of ->
  1777.         jp prma2        ;and go add the member address
  1778.  
  1779. prmae:  ld de,stg17    
  1780.         call perr
  1781.  
  1782. prma2:  call igsht
  1783.         cp varcd
  1784.         jp z,prma3
  1785.  
  1786. prmae2: call sexpas
  1787.         ld de,stg19
  1788.         jp perr
  1789.  
  1790. prma3:  call lookup
  1791.         lda typ1
  1792.         and 80h
  1793.         jp nz,prma4
  1794. prma3b: ld de,stg19     ;bad member name found
  1795.         call perr
  1796.         jp primg4
  1797.  
  1798. prma4:  call primap
  1799.         call tcnst1     ;now, if base is a constant, don't bother generating
  1800.         jp nz,prma5     ;any code. is it a constant?
  1801.         push hl
  1802.         lhld svv1       ;yes. Add member offset to svv1.
  1803.         add hl,de
  1804.         shld svv1       ;now wasn't that easy?
  1805.         pop hl
  1806.         jp primg4       ;go skip over the code generation part
  1807.  
  1808. prma5:  push de
  1809.         call flshh1     ;make sure base is in HL
  1810.         pop de
  1811.         call maddd
  1812. prma6:  xor a
  1813.         sta sval1
  1814.         jp primg4
  1815.  
  1816. ;
  1817. ; Handle "." operator:
  1818. ;
  1819.  
  1820. primp:  call tsval
  1821.         jp nz,primp2
  1822.         ld de,stg17
  1823.         call perr
  1824. primp2: inc hl
  1825.         call igsht
  1826.         cp varcd
  1827.         jp nz,prmae2
  1828.         call lookup
  1829.         lda typ1
  1830.         and 80h
  1831.         jp z,prma3b
  1832.         call tcnst1
  1833.         jp z,primp3
  1834.         push de
  1835.         call flshh1     ;if not constant, get base in HL
  1836.         pop de
  1837.         jp prma4        ;and go add member displacement value
  1838.  
  1839. primp3: push hl
  1840.         lhld svv1
  1841.         add hl,de
  1842.         shld svv1
  1843.         pop hl
  1844.         call primap
  1845.         jp primg4
  1846.  
  1847. primap: lda typ1
  1848.         and 7fh
  1849.         sta typ1
  1850.  
  1851. ;       and 20h
  1852. ;       ret nz
  1853.  
  1854.         ;nop
  1855.         ;nop
  1856.         ;nop ;???
  1857.  
  1858.         lda indc1
  1859.         inc a
  1860.         sta indc1
  1861.         xor a
  1862.         sta value
  1863.         ret
  1864.  
  1865.  
  1866. ;
  1867. ; Handle ++ and -- operation on lvalue:
  1868. ;
  1869.  
  1870. prim30: lda val
  1871.         or a            ;check if we need result value
  1872.         jp nz,prim30b   ;if so, get it.
  1873.         call igsht      ;else no value explicitly needed
  1874.         call primop     ;trailing primary operator?
  1875.         jp z,prim30a    ;if so, play safe & force value
  1876.         ld a,b          ;else optimize for no result value!
  1877.         and 0feh        ;and make post ops into pre ops
  1878.         ld b,a
  1879.         jp prim30b
  1880.  
  1881. prim30a: ld a,1
  1882.          sta val
  1883.  
  1884. prim30b: call prm30
  1885.         xor a
  1886.         sta frml1
  1887.         ret
  1888.  
  1889. prm30:  ld a,1
  1890.         sta value
  1891.         call analyz
  1892.         lda asnokf
  1893.         or a
  1894.         jp z,p30err
  1895.         lda amathf
  1896.         or a
  1897.         jp nz,p30a
  1898. p30err: ld de,stg8a
  1899.         jp perr
  1900.  
  1901. p30a:   lda avar
  1902.         or a
  1903.         jp z,p30b
  1904.         xor a
  1905.         sta indc1
  1906.         lda typ1
  1907.         or a
  1908.         jp nz,p30a2
  1909.         lda val
  1910.         ld c,0
  1911.         or a
  1912.         jp z,domac
  1913.         inc c
  1914.         jp domac
  1915.  
  1916. p30a2:  lda sval1       ;abs external addr?
  1917.         and 1
  1918.         jp nz,p30a3
  1919.  
  1920.         ld c,2          ;no.
  1921.         call domac
  1922.         inc c
  1923.         lda val
  1924.         or a
  1925.         call nz,domac
  1926.         ld a,40h
  1927.         sta sval1
  1928.         ret
  1929.  
  1930. p30a3:  push hl         ;yes.
  1931.         lhld svv1
  1932.         shld sr0
  1933.         pop hl
  1934.         ld c,8
  1935.         call domac
  1936.         inc c
  1937.         lda val
  1938.         or a
  1939.         call nz,domac
  1940.         xor a
  1941.         sta sval1
  1942.         ret
  1943.  
  1944.  
  1945. p30b:   lda sval1       ;abs external addr?
  1946.         and 1
  1947.         jp nz,p30g
  1948.  
  1949.         ld de,m20       ;no.
  1950.         lda optimf      ;-z7 in effect?
  1951.         and 40h
  1952.         jp z,p30ba
  1953.         ld de,m20z
  1954.  
  1955. p30ba:  call mcrog
  1956.         lda val
  1957.         or a
  1958.         jp z,p30c
  1959.         call ckle2
  1960.         jp z,p30c
  1961.         ld c,4
  1962.         call domac
  1963. p30c:   call ckle2
  1964.         jp nz,p30d
  1965.         ld c,5
  1966.         call domac
  1967.         lda asize
  1968.         dec a
  1969.         jp z,p30e
  1970.         ld c,5
  1971.         call domac
  1972.         jp p30e
  1973.  
  1974. p30d:   push hl
  1975.         lhld asize
  1976.         shld sr0
  1977.         ld a,l
  1978.         sta sr1+1
  1979.         ld a,h
  1980.         sta sr2+1
  1981.         ld a,0d6h
  1982.         sta sr1
  1983.         ld a,0deh
  1984.         sta sr2
  1985.         pop hl
  1986.         ld c,6
  1987.         call domac
  1988. p30e:   ld de,m28
  1989.         call mcrog
  1990.         ld a,40h
  1991.         sta sval1
  1992.         lda val
  1993.         or a
  1994.         ret z
  1995.  
  1996.         call ckle2
  1997.         jp z,p30f
  1998.         ld c,7
  1999.         jp domac
  2000.  
  2001. p30f:   ld c,3
  2002.         call domac
  2003.         lda asize
  2004.         dec a
  2005.         ld c,3
  2006.         call nz,domac
  2007.         ret
  2008.  
  2009. p30g:   push hl         ;yes, abs external addr.
  2010.         lhld svv1
  2011.         shld sr0
  2012.         pop hl
  2013.         ld de,mac40     ;do 'lhld foo'
  2014.         call mcrog
  2015.         lda val         ;need value result?
  2016.         or a
  2017.         jp z,p30h
  2018.         call ckle2      ;yes.
  2019.         jp z,p30h
  2020.         ld c,10 ;push old value
  2021.         call domac
  2022. p30h:   call ckle2
  2023.         jp nz,p30i
  2024.         ld c,11
  2025.         call domac
  2026.         lda asize
  2027.         dec a
  2028.         jp z,p30j
  2029.         ld c,11
  2030.         call domac
  2031.         jp p30j
  2032.  
  2033. p30i:   push hl
  2034.         lhld asize
  2035.         shld sr1
  2036.         call cmh
  2037.         shld sr2
  2038.         pop hl
  2039.         ld c,12
  2040.         call domac
  2041. p30j:   ld de,mac09     ;do: 'shld foo'
  2042.         call mcrog
  2043.         xor a
  2044.         sta sval1       ;result in HL
  2045.         lda val         ;need result?
  2046.         or a
  2047.         ret z           ;if not, all done
  2048.         call ckle2      ;else restore former value...
  2049.         jp z,p30k
  2050.         ld c,13
  2051.         jp domac
  2052.  
  2053. p30k:   ld c,9
  2054.         call domac
  2055.         lda asize
  2056.         dec a
  2057.         ld c,9
  2058.         call nz,domac
  2059.         ret
  2060.  
  2061.  
  2062. ckgt2:  lda asize+1
  2063.         or a
  2064.         jp nz,invrt
  2065.         lda asize
  2066.         cp 3
  2067.         ret c
  2068.         xor a
  2069.         ret
  2070.  
  2071. ckle2:  call ckgt2
  2072.         jp invrt
  2073.  
  2074. mact:   dw m12a,m12a,m14a,m14a          ;c = 0
  2075.         dw m12,m13,m14,m15              ;c = 1
  2076. mactz:  dw m16b,m16b,m18,m18            ;c = 2
  2077.         dw mnul,m23,mnul,m22            ;c = 3
  2078.         dw mnul,m21,mnul,m21            ;c = 4
  2079.         dw m22,m22,m23,m23              ;c = 5
  2080.         dw m26,m26,m27,m27              ;c = 6
  2081.         dw mnul,m30,mnul,m30            ;c = 7
  2082.  
  2083.         dw me16b,me16b,me18,me18        ;c = 8
  2084.         dw mnul,me23,mnul,me22          ;c = 9
  2085.         dw mnul,me21,mnul,me21          ;c = 10
  2086.         dw me22,me22,me23,me23          ;c = 11
  2087.         dw me26,me26,me27,me27          ;c = 12
  2088.         dw mnul,me30,mnul,me30          ;c = 13
  2089.  
  2090.  
  2091. ;
  2092. ; New ALU code generator for v1.4
  2093. ;       info2 OP inf1 --> destination
  2094. ;
  2095. ; where info2 is either: a) in a reg, b) a constant, or c) on the stack,
  2096. ;  and  info1 is either: a) in a reg, b) a constant, or c) a flag setting
  2097. ;  and  destination is either a register or a constant.
  2098. ;
  2099.  
  2100. alugen: sta op          ;save operator code
  2101.         xor a           ;clear "make result type that of info2" flag
  2102.         sta par2pf      ;and clear "two pointers" flag
  2103.         call nolvs      ;make sure there aren't any flag settings
  2104.         call tpshd      ;info2 pushed?
  2105.         jp nz,alugo     ;if not, all set to compute
  2106.         call tcnst1     ;yes. is info1 a constant?
  2107.         jp z,alu1               ;if so, go pop info2 into DE
  2108.         lda sval1       ;no...is info1 value in HL?
  2109.         and 0c0h
  2110.         jp nz,alu2      ;if not, pop info2 into HL
  2111. alu1:   call gpopd      ;pop info2 into DE
  2112.         ld a,40h
  2113.         jp alu3
  2114. alu2:   call gpoph      ;pop info2 into HL
  2115.         xor a
  2116. alu3:   sta sval2       ;tell that value is now in the appropriate reg
  2117.         jp alugo
  2118.  
  2119.  
  2120. ;
  2121. ; Make sure we don't have any flag settings to bum around with
  2122. ;
  2123.  
  2124. nolvs:  lda sval1       ;info1 a flag setting?
  2125.         and 4
  2126.         jp z,nolvs2
  2127.         lda sval1       ;yes. value too?
  2128.         and 24h
  2129.         cp 24h
  2130.         jp nz,nolvs1
  2131.         lda sval1       ;yes-make value only (preserving register bits)
  2132.         and 0c0h
  2133.         sta sval1
  2134.         jp nolvs2
  2135.  
  2136. nolvs1: lda sval2       ;info1 is flag only. is info2 in HL?   
  2137.         and 0c3h
  2138.         jp z,flshd1     ;if so, put value in DE
  2139.         jp flshh1       ;else put it in HL
  2140.  
  2141. nolvs2: lda sval2       ;info2 a flag setting?
  2142.         and 4
  2143.         ret z
  2144.         lda sval2       ;yes. do we have a value already?
  2145.         and 24h
  2146.         cp 24h
  2147.         jp nz,nolvs3
  2148.         lda sval2       ;yes. make value only, preserving register
  2149.         and 0c0h
  2150.         sta sval2
  2151.         ret
  2152.  
  2153. nolvs3: lda sval1       ;info2 is flag only. info1 in HL?
  2154.         and 0c3h
  2155.         jp z,flshd2     ;if so, put value in DE
  2156.         jp flshh2       ;else put in HL
  2157.  
  2158. ;
  2159. ; Flush all relative constants into registers
  2160. ;
  2161.  
  2162. flrcn:  lda sval1       ;info1 a rel const?
  2163.         and 2
  2164.         jp z,frcn2      ;if not, go check out info2
  2165.         call tcnst2     ;info2 a constant?
  2166.         jp nz,frcn1
  2167.  
  2168.         call flshh1     ;yes-flush info1 into HL
  2169.         jp flrcn        ;and go take care of info2
  2170.  
  2171. frcn1:  lda sval2       ;info1 is rel lv. bummer. push info2
  2172.         and 0c0h
  2173.         call z,gpushh
  2174.         call nz,gpushd
  2175.         call flshh1     ;flush info1 into HL
  2176.         call gpopd      ;get info2 back into DE
  2177.         ld a,40h        ;tell that info2 is in DE
  2178.         sta sval2
  2179.         ret
  2180.  
  2181.  
  2182. frcn2:  lda sval2       ;info1 NOT a rel constant. info2 a rel const lv?
  2183.         and 2
  2184.         ret z           ;if not, all done
  2185.  
  2186.         call tcnst1     ;yes--info1 an abs constant?
  2187.         jp nz,frcn3
  2188.         call flshh2     ;yes, so flush info2 into HL
  2189.         ret    
  2190.  
  2191. frcn3:  lda sval1       ;info2 is rel lv. bummer. push info1
  2192.         and 0c0h
  2193.         call z,gpushh
  2194.         call nz,gpushd
  2195.         call flshh2     ;flush info2 into HL
  2196.         call gpopd      ;get info2 back into DE
  2197.         ld a,40h        ;tell that info2 is in DE
  2198.         sta sval1
  2199.         ret
  2200.  
  2201.  
  2202. alugo:  push hl         ;do this to preserve text ptr in HL
  2203.         xor a
  2204.         sta wierdp
  2205.         call alugo1
  2206.         pop hl
  2207.         ret
  2208.  
  2209. wierdp: ds 1            ;true for: (info2 - info1), when info2 ptr & info1 val
  2210.  
  2211. alugo1: lhld svv1
  2212.         shld sr0
  2213.         lhld svv2
  2214.         shld sr1
  2215.         lda op
  2216.  
  2217.         cp eqcd ;== and not= are special
  2218.         jp z,alueq
  2219.         cp neqcd
  2220.         jp z,alune
  2221.  
  2222.         call analyz
  2223.         lda amathf
  2224.         or a
  2225.         jp z,parerr
  2226.  
  2227.         call anal2
  2228.         lda amathf
  2229.         or a
  2230.         jp z,parerr
  2231.  
  2232.         xor a
  2233.         sta hbn1cf
  2234.  
  2235.         lhld indc1      ;turn all characters into
  2236.         call aluadj     ;integers, and adjust attributes
  2237.         shld indc1      ;as required.
  2238.         call z,clhbn1
  2239.         lhld indc2
  2240.         call aluadj
  2241.         shld indc2
  2242.         call z,clhbn2
  2243.  
  2244.         lda op
  2245.         cp mulcd
  2246.         jp nz,aludiv
  2247.  
  2248.  
  2249.         call usuals     ;handle `*' op
  2250.         ld de,smmulu
  2251.         jp z,spcash
  2252.         ld de,smmuls
  2253.         jp spcash
  2254.  
  2255. aludiv: cp divcd
  2256.         jp nz,alumod
  2257.         call usuals     ;handle `/' op
  2258.         ld de,smdivu
  2259.         jp z,spcash
  2260.         ld de,smdivs
  2261.         jp spcash
  2262.  
  2263. alumod: cp modcd
  2264.         jp nz,aluadd
  2265.         call usuals     ;handle `%' op
  2266.         ld de,smmodu
  2267.         jp z,spcash
  2268.         ld de,smmods
  2269.         jp spcash
  2270.  
  2271. aluadd: cp plus
  2272.         jp nz,alusub
  2273.         call nolvwr     ;permit no rel-lvalue/reg-value combinations
  2274.         call paradj     ;handle `+' op
  2275.  
  2276.         call tbabsc
  2277.         ld de,smadd
  2278.         jp nz,spcash
  2279.  
  2280.         lhld svv1       ;handle simple constants here
  2281.         ex de,hl
  2282.         lhld svv2
  2283.         add hl,de
  2284.         shld svv1
  2285.         lda wierdp      ;need to copy sval2 to sval1?
  2286.         or a
  2287.         ret z
  2288.  
  2289. aluad3: lda sval2
  2290.         and 3fh
  2291.         ld b,a
  2292.         lda sval1
  2293.         and 0c0h
  2294.         or b
  2295.         sta sval1       ;yes, so do it
  2296.         ret
  2297.  
  2298. ;
  2299. ; Make sure we don't end up with one operand being a relative lvalue
  2300. ; constant and the other a value in a register:
  2301. ;
  2302.  
  2303. nolvwr: lda sval1
  2304.         and 3           ;info1 in a reg?
  2305.         jp z,flrcn      ;if so, go flush info2 if it is a rel lvalue
  2306.         lda sval2
  2307.         and 3           ;info2 in a reg?
  2308.         jp z,flrcn      ;if so, go flush info1 if it is a rel lvalue
  2309.         ret
  2310.  
  2311. alusub: cp mincd
  2312.         jp nz,alusr
  2313.         call nolvwr     ;permit no rel-lvalue/reg-value combinations
  2314.         call paradj     ;handle `-' op
  2315.         call tbabsc
  2316.         ld de,smsub
  2317.         call nz,spcash
  2318.         lhld svv1       ;do this just in case we had two constants
  2319.         call cmh
  2320.         ex de,hl
  2321.         lhld svv2
  2322.         add hl,de
  2323.         shld svv1
  2324.  
  2325.         lda par2pf      ;two pointers?
  2326.         or a
  2327.         jp nz,alus1     ;if so, go scale result by object size
  2328.        
  2329.         lda wierdp      ;no. Was it an (ptr - val) expression?
  2330.         or a
  2331.         jp nz,aluad3    ;if so, go set info1 to type of info2
  2332.         ret             ;else info1 is correct type-all done.
  2333.  
  2334.  
  2335. alus1:  lhld asize      ;we've gotta scale result by object size
  2336.         shld sr0
  2337.         dec hl
  2338.         ld a,h
  2339.         or l            ;size = 1?
  2340.         jp z,alus2      ;if so, don't do nuthin'
  2341.         ld de,macad3    ;else gen code to divide by object size
  2342.         call tbabsc
  2343.         call nz,mcrog   ;but don't bother if both constants
  2344.         call z,divs1a   ;in case they're constants, calculate value here
  2345. alus2:  ld hl,0
  2346.         shld dimsz1
  2347.         xor a
  2348.         sta indc1
  2349.         inc a
  2350.         sta typ1
  2351.         call tbabsc     ;if both were abs constants,
  2352.         ret nz
  2353.         ld a,1
  2354.         sta sval1       ;result is ABS constant (even if both args were lv's)
  2355.         ret
  2356.  
  2357. alusr:  cp srcd
  2358.         jp nz,alusl
  2359.         call ckval2     ;handle `>>' op
  2360.         call flrcn
  2361.         call tbabsc
  2362.         ld de,smsr
  2363.         jp nz,spcash
  2364.         lhld svv2       ;do constant case
  2365.         lda svv1
  2366.         ld b,a
  2367.         inc b
  2368. alusr2: dec b
  2369.         jp z,alusl3
  2370.         xor a
  2371.         ld a,h
  2372.         rra    
  2373.         ld h,a
  2374.         ld a,l
  2375.         rra
  2376.         ld l,a
  2377.         jp alusr2
  2378.  
  2379.  
  2380. alusl:  cp slcd
  2381.         jp nz,alugt
  2382.         call ckval2     ;handle `<<' op
  2383.         call flrcn
  2384.         call tbabsc
  2385.         ld de,smsl
  2386.         jp nz,spcash
  2387.         lhld svv2       ;do constant case
  2388.         lda svv1
  2389.         inc a
  2390. alusl2: dec a
  2391.         jp z,alusl3
  2392.         add hl,hl
  2393.         jp alusl2
  2394.  
  2395. alusl3: shld svv1
  2396.         ret
  2397.  
  2398. alugt:  cp gtcd
  2399.         jp nz,aluge
  2400. alugt2: call usual2     ;do '>' op
  2401.         ld de,smgtu
  2402.         jp z,spcash
  2403.         ld de,smgts
  2404.         jp spcash
  2405.  
  2406. aluge:  cp gecd
  2407.         jp nz,alult
  2408.         call alult2     ;do '>=' (simply inverse of '<')
  2409.         jp alune1
  2410.  
  2411. alult:  cp ltcd
  2412.         jp nz,alule
  2413. alult2: call usual2     ;do '<' op
  2414.         ld de,smltu
  2415.         jp z,spcash
  2416.         ld de,smlts
  2417.         jp spcash
  2418.  
  2419. alule:  cp lecd
  2420.         jp nz,aluand
  2421.         call alugt2     ;do '<=' (simply inverse of '>')
  2422.         jp alune1
  2423.  
  2424. aluand: cp ancd
  2425.         jp nz,aluxor
  2426.         call ckval2     ;do '&' op
  2427.         call flrcn
  2428.         call tbabsc
  2429.         ld de,smand
  2430.         jp nz,spcash
  2431.         lhld svv1       ;handle trivials constant case
  2432.         lda svv2
  2433.         and l
  2434.         ld l,a
  2435.         lda svv2+1
  2436.         and h
  2437.         ld h,a
  2438.         shld svv1
  2439.         ret
  2440.  
  2441. aluxor: cp xorcd
  2442.         jp nz,aluor
  2443.         call ckval2     ;do '^' op
  2444.         call flrcn
  2445.         call tbabsc
  2446.         ld de,smxor
  2447.         jp nz,spcash
  2448.         lhld svv1       ;do simple constants case
  2449.         lda svv2
  2450.         xor l
  2451.         ld l,a
  2452.         lda svv2+1
  2453.         xor h
  2454.         ld h,a
  2455.         shld svv1
  2456.         ret
  2457.  
  2458. aluor:  cp orcd
  2459.  
  2460.         push de
  2461.         ld de,stgbbo    ;'expecting binary operator'
  2462.         call nz,perrab  ;no other operators; better be '|'
  2463.         pop de
  2464.  
  2465.         call ckval2
  2466.         call flrcn
  2467.         call tbabsc
  2468.         ld de,smor
  2469.         jp nz,spcash
  2470.         lhld svv1       ;do trivial constants case
  2471.         lda svv2
  2472.         or l
  2473.         ld l,a
  2474.         lda svv2+1
  2475.         or h
  2476.         ld h,a
  2477.         shld svv1
  2478.         ret
  2479.  
  2480. alune:  call alueq      ;for not=, first call the == routine
  2481. alune1: lda sval1       ;and invert the result.
  2482.         and 4           ;was it a flag setting?
  2483.         jp z,alune2
  2484.         lda sbmap1      ;yes-invert bit 0
  2485.         xor 1
  2486.         sta sbmap1
  2487.         ret
  2488.  
  2489. alune2: lda sval1
  2490.         and 3           ;result a constant?
  2491.         call z,ierror   ;if not, must've screwed up somewhere
  2492.         lhld svv1       ;get result of == test
  2493. alun2a: ld a,h
  2494.         or l
  2495.         ld hl,0         ;was it zero?
  2496.         jp nz,alune3    ;if not, new result IS zero
  2497.         inc hl          ;if so, new result is 1
  2498. alune3: shld svv1
  2499.         ret
  2500.                         ;handle == operator:
  2501. alueq:  call flrcn      ;flush rel lvalue constants
  2502.         call tbabsc
  2503.         jp nz,alueq2    ;both constants?
  2504.         lhld svv1       ;yes.
  2505.         ex de,hl
  2506.         lhld svv2       ;compare them
  2507.         call cmh
  2508.         add hl,de               ;set HL to zero if two are equal
  2509.         jp alun2a
  2510.  
  2511. alueq2: lda sval1
  2512.         sta ssval
  2513.         call tschr      ;info1 a simple char?
  2514.         jp nz,aleq3
  2515.         call tschr2     ;yes. info2 also a char?
  2516.         jp nz,aleq2b
  2517.         ld de,mac71c    ;yes--do simple ld a,e-cp l
  2518.         call mcrog
  2519. aleq20: xor a
  2520. aleq2a: sta sbmap1
  2521.         ld a,4
  2522.         sta sval1
  2523.         ret
  2524.  
  2525. aleq2b: call tcnst2     ;info1 is a char, info2 isn't..
  2526.         jp nz,aleq2e    ;is info2 a constant?
  2527.         lhld svv2
  2528.         shld svv1       ;if so, xfer value over to common area
  2529. alq2b2: lda svv1+1      ;info1 is a char. is info2 (const) <= 255?
  2530.         or a
  2531.         jp nz,aleq2d
  2532.         lda ssval       ;yes.
  2533.         and 0c0h        ;get low byte of non-constant into A
  2534.         ld a,7dh
  2535.         call z,genb             ;if non-constant in H, do "ld a,l"
  2536.         ld a,7bh
  2537.         call nz,genb    ;else do "ld a,e"
  2538.         lda svv1        ;special case constant of 0?
  2539.         or a
  2540.         jp nz,aleq2g
  2541.         ld a,0b7h       ;if so, do "or a"
  2542.         call genb
  2543.         jp aleq20
  2544.  
  2545. aleq2g: ld a,0feh       ;do 'cp value'
  2546.         call genb
  2547.         lda svv1
  2548.         call genb
  2549.         jp aleq20
  2550.  
  2551. aleq2d: ld hl,0         ;if char value and two byte constant,
  2552.         shld svv1       ;can't possibly be equal
  2553.         ld a,1
  2554.         sta sval1
  2555.         ret
  2556.  
  2557. aleq2e: ld de,mac61     ;zero high-order byte of char value
  2558.         lda ssval
  2559.         and 0c0h
  2560.         call z,mcrog
  2561.         ld de,mac62
  2562.         call nz,mcrog
  2563.         ld de,mac71
  2564.         call mcrog
  2565.         jp aleq20
  2566.  
  2567. aleq3:  call tschr2     ;info1 NOT char, but is info2?
  2568.         jp nz,aleq4
  2569.         lda sval2       ;yes--set up info2 attributes in common area
  2570.         sta ssval
  2571.         call tcnst1     ;if info1 not constant, go zero high byte of
  2572.         jp nz,aleq2e    ;info2 and do 16-bit test
  2573.         jp alq2b2       ;else optimize for character constant
  2574.  
  2575. aleq4:  ld de,smeq      ;do the normal macro for 2 values or one constant
  2576.         jp spcash       ;and one big value.
  2577.  
  2578.  
  2579.  
  2580.  
  2581. ;
  2582. ; If one or two pointers appear in a + or - operation, scale
  2583. ; the non-pointer by the size of the object the pointer points to:
  2584. ;
  2585.  
  2586. paradj: call unsadj     ;adjust for unsigned operands
  2587.         call tptr2      ;info2 a pointer?
  2588.         jp z,prdj2
  2589.         call tptr       ;no. info1 a pointer?
  2590.         ret nz          ;if not, nothin' to do.
  2591.         lda op
  2592.         cp mincd
  2593.         jp z,parerr     ;2nd arg can't be pointer in binary `-' operation
  2594.         call analyz
  2595.         lhld svv2
  2596.         shld subval
  2597.         lhld asize
  2598.         shld sr0
  2599.         lda sval2
  2600.         call sclabh     ;scale object described by A by HL bytes
  2601.         shld svv2       ;save value in case of constant (such as array base)
  2602.         ret
  2603.  
  2604. prdj2:  call tptr       ;info2 is ptr-is info1 ptr too?
  2605.         jp nz,prdj3
  2606.         lda op          ;yes. Can only subtract 2 ptrs if op is `-'
  2607.         cp mincd
  2608.         jp nz,parerr
  2609.         call analyz
  2610.         push hl
  2611.         lhld asize
  2612.         push hl         ;save size of object 1
  2613.         call anal2
  2614.         lhld asize      ;get size of object 2 in HL
  2615.         pop de          ;get size of object 1 in DE
  2616.         ld a,h          ;compare size of both objects--must be =
  2617.         cp d
  2618.         ld a,l
  2619.         pop hl
  2620.         jp nz,parerr
  2621.         cp e
  2622.         jp nz,parerr
  2623.         ld a,1
  2624.         sta par2pf
  2625.         ret
  2626.  
  2627. prdj3:  call anal2      ;info2 is a pointer.
  2628.         lhld svv1
  2629.         shld subval
  2630.         lhld asize
  2631.         shld sr0
  2632.         lda sval1
  2633.         call sclabh     ;scale asize by HL
  2634.         shld svv1
  2635.  
  2636.         lhld indc2      ;lde info2 info into info1, but
  2637.         shld indc1      ;preserve info1's old sval1 and svv1
  2638.         lhld dimsz2     ;for register allocation/optimization
  2639.         shld dimsz1     ;purposes.
  2640.         lhld strsz2
  2641.         shld strsz1
  2642.         ld a,1
  2643.         sta wierdp
  2644.         ret
  2645.  
  2646. sclabh: ld b,a          ;object to scale a constant?
  2647.         and 3
  2648.         jp z,scl2
  2649.         call mult       ;yes--simple
  2650.         ret
  2651.  
  2652. scl2:   ld a,h          ;multiply by 0?
  2653.         or l
  2654.         ret z           ;if so, just grin and scratch hair.
  2655.         dec hl          ;multiply by 1?
  2656.         ld a,h
  2657.         or l
  2658.         ret z           ;if so, don't do a darned thing
  2659.         ld a,b          ;else, is value to scale in HL?
  2660.         and 0c0h
  2661.         jp nz,sclde
  2662.         call trydad     ;yes, try to do it with 'add hl,hl's
  2663.         ret z           ;all done if it worked
  2664.         ld de,macad2    ;else scale HL the hard way
  2665.         call mcrog
  2666.         ret
  2667.  
  2668. sclde:  lda codflg      ;if value in DE, first see if we can use 'add hl,hl's
  2669.         push af
  2670.         xor a
  2671.         sta codflg      ;disable code generation the first time...
  2672.         push hl
  2673.         call trydad
  2674.         pop hl 
  2675.         jp nz,sclde2    ;can we use "add hl,hl"'s?
  2676.         pop af          ;yes. restore codeflag
  2677.         sta codflg
  2678.         call gexdehl    ;get the value from DE into HL
  2679.         call trydad     ;do the add hl,hl's for real
  2680.         lda op          ;if + operator, don't worry about restoring
  2681.         cp plus ;proper registers (leave them switched)
  2682.         call nz,gexdehl ;but put them back if - operator
  2683.         ret
  2684.  
  2685. sclde2: pop af          ;restore codflg
  2686.         sta codflg
  2687.         ld de,macad1    ;and scale DE the hard way
  2688.         call mcrog
  2689.         ret
  2690.  
  2691.  
  2692. trydad: ld a,h
  2693.         or a            ;if high byte is non-zero, forget about
  2694.         ret nz          ;using add hl,hl's!
  2695.         ld c,29h
  2696.         ld a,l
  2697.         dec a
  2698.         jp z,dad1               ;if HL was originally 2, go do single add hl,hl
  2699.         sub 2
  2700.         jp z,dad2               ;if it was 4, do two add hl,hl's
  2701.         sub 4
  2702.         jp z,dad3               ;if it was 8, do three add hl,hl's
  2703.         sub 8           ;if wasn't 16, give up
  2704.         ret nz
  2705.         ld a,c
  2706.         call genb       ;it was 16--do four add hl,hl's
  2707. dad3:   ld a,c
  2708.         call genb
  2709. dad2:   ld a,c
  2710.         call genb
  2711. dad1:   ld a,c
  2712.         call genb
  2713.         ret
  2714.  
  2715.  
  2716.  
  2717. ;
  2718. ; svv1 <-- svv1/asize, signed
  2719. ;
  2720.  
  2721. divs1a: lhld svv1
  2722.         ld a,h
  2723.         or a
  2724.         jp p,divpos     ;svv1 positive? if so, do simple unsigned divide
  2725.         call cmh        ;else negate to make it positive,
  2726.         call divpos     ;do the divide
  2727.         lhld svv1       ;and negate the result
  2728.         call cmh
  2729.         shld svv1
  2730.         ret
  2731.  
  2732. ;
  2733. ; svv1 <-- HL/asize, unsigned:
  2734. ;
  2735.  
  2736. divpos: ld bc,-1        ;quotient result
  2737.         ex de,hl
  2738.         lhld asize
  2739.         call cmh
  2740.         ex de,hl                ;put -asize in DE
  2741. divtst: ld a,h
  2742.         or a            ;if HL negative, all done
  2743.         jp p,keepon
  2744.         ld h,b
  2745.         ld l,c
  2746.         shld svv1       ;store quotient
  2747.         ret
  2748.  
  2749. keepon: add hl,de               ;subtract asize again
  2750.         inc bc
  2751.         jp divtst       ;and test for negative numerator
  2752.  
  2753.  
  2754. ;
  2755. ; Some common tests performed by alugen operator handlers:
  2756. ;
  2757.  
  2758. usuals: call ckval2
  2759. usual2: call flrcn
  2760.         call tbabsc
  2761.         call z,fcnsts
  2762.         call unsadj
  2763.         ret
  2764.  
  2765. ;
  2766. ; Clear high byte of info1's register:
  2767. ;
  2768.  
  2769. clhbn1: ld a,0afh       ;get 'xor a'
  2770.         call genb
  2771.         lda sval1
  2772. clhb1a: and 0c0h       
  2773.         ld a,67h        ;'ld h,a'
  2774.         call z,genb
  2775.         ld a,57h        ;'ld d,a'
  2776.         call nz,genb
  2777.         sta hbn1cf
  2778.         ret
  2779.  
  2780. ;
  2781. ; Clear high byte of info2's register:
  2782. ;
  2783.  
  2784. clhbn2: lda hbn1cf
  2785.         or a
  2786.         lda sval2       ;if info1 already cleared, use the 0 in A again
  2787.         jp nz,clhb1a
  2788.         ld de,mac61     ;else generate ld x,0
  2789.         and 0c0h
  2790.         call z,mcrog    ;ld h,0 if value in HL
  2791.         ld de,mac62
  2792.         call nz,mcrog   ;else ld d,0
  2793.         ret
  2794.  
  2795. ;
  2796. ; Return Z set if both info1 and info2 are constants of some kind:
  2797. ;
  2798.  
  2799. tbabsc: lda sval1
  2800.         and 3
  2801.         jp z,invrt
  2802.         lda sval2
  2803.         and 3
  2804.         jp invrt
  2805.  
  2806. ;
  2807. ; Flush any and all constants into registers
  2808. ;
  2809.  
  2810. fcnsts: lda sval1       ;info1 a const?
  2811.         and 3
  2812.         jp z,fcn2               ;if not, go check out info2
  2813.         lda sval2       ;yes. info2 a const?
  2814.         and 3
  2815.         jp z,fcn1
  2816.         call flshd1     ;yes-flush info1 into DE
  2817.         jp fcnsts       ;and go take care of info2
  2818.  
  2819. fcn1:   lda sval1       ;info1 constant, info2 isn't. info1 absolute?
  2820.         and 1
  2821.         jp z,fcn1a
  2822.         lda sval2       ;yes, so flush into wherever info2 isn't...
  2823.         and 0c0h
  2824.         jp z,flshd1     ;either DE, if info2 in HL
  2825.         jp flshh1       ;or into HL if info2 in DE
  2826.  
  2827. fcn1a:  lda sval2       ;info1 is rel lv. bummer. push info2
  2828.         and 0c0h
  2829.         call z,gpushh
  2830.         call nz,gpushd
  2831.         call flshh1     ;flush info1 into HL
  2832.         call gpopd      ;get info2 back into DE
  2833.         ld a,40h        ;tell that info2 is in DE
  2834.         sta sval2
  2835.         ret
  2836.  
  2837.  
  2838. fcn2:   lda sval2       ;info1 NOT a constant. info2 a const?
  2839.         and 3
  2840.         ret z           ;if not, all done
  2841.         lda sval2       ;yes. absolute constant?
  2842.         and 1
  2843.         jp z,fcn2a
  2844.         lda sval1       ;yes-flush into wherever info1 isn't
  2845.         and 0c0h
  2846.         jp z,flshd2     ;into DE if info1 in HL
  2847.         jp flshh2       ;into HL if info1 in DE
  2848.  
  2849. fcn2a:  lda sval1       ;info2 is rel lv. bummer. push info1
  2850.         and 0c0h
  2851.         call z,gpushh
  2852.         call nz,gpushd
  2853.         call flshh2     ;flush info2 into HL
  2854.         call gpopd      ;get info2 back into DE
  2855.         ld a,40h        ;tell that info2 is in DE
  2856.         sta sval1
  2857.         ret
  2858.  
  2859.         ;IF LASM
  2860.         ;link cc2c
  2861.         ;ENDIF
  2862.