home *** CD-ROM | disk | FTP | other *** search
/ 8bitfiles.net/archives / archives.tar / archives / genie-commodore-file-library / C64-128Toolkit / ACE12-AS-SRC.ARC / ACE12-AS.S < prev   
Encoding:
Text File  |  2019-04-13  |  89.7 KB  |  4,758 lines

  1. ;*** as v1.00 program: one-pass assembler  -  by Craig Bruce  -  15-Oct-1994
  2.  
  3. ; This is the ACE-assembler version of the program
  4.  
  5. ;todo: -implement storage classes: $00=internal, $01=rel.label, $80=exported
  6. ;      -implement all var types: 0=value, 1=address, 2=addr.high, 3=addr.low
  7. ;      -implement source column, make line:col point to start of cur token
  8. ;      -make it so you can use a "\<CR>" to continue a line
  9. ;      -add more operators: * / & | ~  full precedence?
  10. ;      -cache current symbol
  11.  
  12. ;--> include acehead.s
  13. ;===ace system interface declarations===
  14.  
  15. zp      = $f8  ;(2)
  16. zw      = $fa  ;(2)
  17. mp      = $fc  ;(4)
  18. syswork = $80  ;(16)
  19.  
  20. aceStatB         = $f00
  21. errno            = aceStatB+0          ;(1)
  22. aceID            = aceStatB+2          ;(2)
  23. aceArgc          = aceStatB+4          ;(2)
  24. aceArgv          = aceStatB+6          ;(2)
  25. aceMemTop        = aceStatB+8          ;(2)
  26. aceShellPath     = $c00                ;(256)
  27. aceShellAlias    = $d00                ;(256)
  28. aceCurDirName    = aceStatB+$80        ;(128)
  29. aceExitData      = $e00                ;(256)
  30. aceDirentBuffer  = aceStatB+10         ;(aceDirentLength)
  31. aceDirentBytes   = aceDirentBuffer+0   ;(4)
  32. aceDirentDate    = aceDirentBuffer+4   ;(8) = YY:YY:MM:DD:HH:MM:SS:TW
  33. aceDirentType    = aceDirentBuffer+12  ;(4)
  34. aceDirentFlags   = aceDirentBuffer+16  ;(1) = drwx*e-t
  35. aceDirentUsage   = aceDirentBuffer+17  ;(1) = ulshb---
  36. aceDirentNameLen = aceDirentBuffer+18  ;(1)
  37. aceDirentName    = aceDirentBuffer+19  ;(17)
  38. aceDirentLength  = 36
  39.  
  40. aceCallB  = $2803
  41. open      = aceCallB+0   ;( (zp)=Name, .A=Mode ) : .A=fd
  42. close     = aceCallB+3   ;( .A=fd )
  43. read      = aceCallB+6   ;( .X=fd, (zp)=Buf, .AY=Len ) : .AY=(zw)=Len, .Z
  44. write     = aceCallB+9   ;( .X=fd, (zp)=Buf, .AY=Len )
  45. fastopen  = aceCallB+12  ;( (zp)=Name, .A=Mode ) : .A=fd
  46. fastclose = aceCallB+15  ;( .A=fd )
  47. fastread  = aceCallB+18  ;( .X=fd, (zp)=Buf, .AY=Len ) : .AY=(zw)=Len, .Z
  48. bload     = aceCallB+21  ;( (zp)=Name, .AY=LoadAddr, (zw)=Limit+1 ) : .AY=End+1
  49. remove    = aceCallB+24  ;( (zp)=Name )
  50. rename    = aceCallB+27  ;( (zp)=OldName, (zw)=NewName )
  51. devinfo   = aceCallB+30  ;( .X=fd ) : .A=DevType, .X=Cols, .Y=Rows
  52. fdswap    = aceCallB+33  ;( .X=fd1, .Y=fd2 )
  53.  
  54. diropen   = aceCallB+36  ;( (zp)=DirName ) : .A=fd
  55. dirclose  = aceCallB+39  ;( .A=fd )
  56. dirread   = aceCallB+42  ;( .X=fd ) : direntBuffer, .Z=eof
  57. isdir     = aceCallB+45  ;( (zp)=Name ) : .A=Dev, .X=isDisk, .Y=isDir
  58. chdir     = aceCallB+48  ;( (zp)=DirName )
  59. cdhome    = aceCallB+51  ;( )
  60. mkdir     = aceCallB+54  ;( (zp)=NewDirName )
  61. rmdir     = aceCallB+57  ;( (zp)=DirName )
  62.  
  63. zpload    = aceCallB+60  ;( [mp]=Source, .X=ZpDest, .Y=Length )
  64. zpstore   = aceCallB+63  ;( .X=ZpSource, [mp]=Dest, .Y=Length )
  65. fetch     = aceCallB+66  ;( [mp]=FarSource, (zp)=Ram0Dest, .AY=Length )
  66. stash     = aceCallB+69  ;( (zp)=Ram0Source, [mp]=FarDest, .AY=length )
  67. pagealloc = aceCallB+72  ;( .A=PageCount, .X=StartTyp, .Y=EndTyp ) : [mp]=FarPtr
  68. pagefree  = aceCallB+75  ;( [mp]=FarPointer, .A=PageCount )
  69.  
  70. winmax    = aceCallB+78  ;( )
  71. wincls    = aceCallB+81  ;( .A=char/color/attrFlags, .X=char, .Y=color )
  72. winset    = aceCallB+84  ;( .A=rows, .X=cols, sw+0=scrRow, sw+1=scrCol )
  73. winsize   = aceCallB+87  ;( ) : <above>+ ,(sw+2)=addr,(sw+4)=rowinc
  74. winput    = aceCallB+90  ;( (sw+0)=addr,(sw+2)=charPtr,.A=attr,.Y=color,.X=len
  75.                             ;  sw+4=fillChar, sw+5=fieldLen )
  76. wincolor  = aceCallB+93  ;( .X=screen, .Y=border, .A=which ) : .X=scr, .Y=bor
  77. winpos    = aceCallB+96  ;( .A=row, .X=col ) : (sw+0)=addr
  78. wincursor = aceCallB+99  ;( (sw+0)=addr, .Y=color, .A=$ff:on/$00:off)
  79. winscroll = aceCallB+102 ;( .A=attr+$08:up+$04:down,.X=rows,sw+4=char,.Y=color)
  80.  
  81. conread   = aceCallB+105 ;( (zp)=Buf, .AY=Len ) : .AY=(zw)=Len, .Z
  82. conwrite  = aceCallB+108 ;( (zp)=Buf, .AY=Len )
  83. conputchar = aceCallB+111 ;( .A=char )
  84. conputlit = aceCallB+114 ;( .A=char )
  85. stopkey   = aceCallB+117 ;( ) : .CC=notPressed
  86. getkey    = aceCallB+120 ;( ) : .A=key
  87. concolor  = aceCallB+123 ;( .A=which, .X=char, .Y=cursor ) : .X=char,.Y=cursr
  88. conpalette = aceCallB+126 ;( ) : sw+0...sw+7=palette [8 colors]
  89. conscreen = aceCallB+129 ;( .A=MinRows, .X=MinCols )
  90. conpos    = aceCallB+132 ;( .A=row, .X=col )
  91.  
  92. exec      = aceCallB+135 ;( (zp)=execName, (zw)=argv, .AY=argCnt, [mp]=saveArea)
  93.                            ;  : .A=exitCode, .X=exitDataLen, [mp]=saveArea
  94. execsub   = aceCallB+138 ;( (zp)=execAddr, (zw)=argv, .AY=argCnt, [mp]=saveArea)
  95.                            ;  : .A=exitCode, .X=exitDataLen, [mp]=saveArea
  96. exit      = aceCallB+141 ;( .A=exitCode, .X=exitBufDataLen, exitData )
  97. memstat   = aceCallB+144 ;( ) : .A=procID, [sw+0]=total, [sw+4]=free
  98.  
  99. utoa      = aceCallB+147 ;( $0+X=value32, (sw+0)=buf, .A=minLen ) :buf, .Y=len
  100. getdate   = aceCallB+150 ;( (.AY)=dateString ) : dateString
  101. setdate   = aceCallB+153 ;( (.AY)=dateString )
  102. cmdopen   = aceCallB+156 ;( (zp)=DevName ) : .A=fd
  103. cmdclose  = aceCallB+159 ;( .A=fd )
  104. cmdsend   = aceCallB+162 ;( .X=fd, (.AY)=CmdString )
  105. cmdstatus = aceCallB+165 ;( .X=fd, (.AY)=StatBufPtr ) : StatBuf, .A=statusCode
  106. grscreen  = aceCallB+168 ;(...)...
  107. grexit    = aceCallB+171 ;(...)...
  108. grfill    = aceCallB+174 ;(...)...
  109. grload    = aceCallB+177 ;(...)...
  110. conkeyavail = aceCallB+180  ;( ) : .CC=keyIsAvailable
  111.  
  112. aceAppAddress = $7000
  113. aceID1 = $cb
  114. aceID2 = $06
  115. aceID3 = 11
  116.  
  117. aceMemNull = $00
  118. aceMemREU = $01
  119. aceMemInternal = $02
  120. aceMemRLREU = $06
  121. aceMemRL = $07
  122.  
  123. aceErrStopped = 0
  124. aceErrTooManyFiles = 1
  125. aceErrFileOpen = 2
  126. aceErrFileNotOpen = 3
  127. aceErrFileNotFound = 4
  128. aceErrDeviceNotPresent = 5
  129. aceErrFileNotInput = 6
  130. aceErrFileNotOutput = 7
  131. aceErrMissingFilename = 8
  132. aceErrIllegalDevice = 9
  133. aceErrWriteProtect = 26
  134. aceErrFileExists = 63
  135. aceErrFileTypeMismatch = 64
  136. aceErrNoChannel = 70
  137. aceErrDiskFull = 72
  138. aceErrInsufficientMemory = 128
  139. aceErrOpenDirectory = 129
  140. aceErrDiskOnlyOperation = 131
  141. aceErrNullPointer = 132
  142. aceErrInvalidFreeParms = 133
  143. aceErrFreeNotOwned = 134
  144. aceErrInvalidWindowParms = 135
  145. aceErrInvalidConParms = 136
  146. aceErrInvalidFileMode = 137
  147. aceErrNotImplemented = 138
  148. aceErrBloadTruncated = 139
  149. aceErrPermissionDenied = 140
  150. aceErrNoGraphicsSpace = 141
  151.  
  152. stdin  = 0
  153. stdout = 1
  154. stderr = 2
  155. ;===end of ace interface declarations===
  156.  
  157. org aceAppAddress
  158.  
  159. jmp main
  160. db aceID1,aceID2,aceID3
  161. db 64,0  ;** stack,reserved
  162.  
  163. ;======== global declarations ========
  164.  
  165. sourceFcb     =  2  ;(1)   ;file control block of current input file
  166. bufptr        =  3  ;(1)   ;byte offset inside of source buffer
  167. sourceLine    =  4  ;(4)   ;source file current line
  168. number        =  8  ;(4)   ;token: 32-bit number value
  169. stringLen     = 12  ;(1)   ;length of string in string buffer
  170. prevChar      = 13  ;(1)   ;previous character scanned, next read (1-too-far)
  171. tokenType     = 14  ;(1)   ;token: type 
  172. tokenNextChar = 15  ;(1)   ;token: next char after token
  173. tokenNumBytes = 16  ;(1)   ;token: number length (1-4 bytes)
  174. tokenChar     = 17  ;(1)   ;token: character
  175. name          = 18  ;(2)   ;pointer to source filename
  176. sourceCol     = 20  ;(1)   ;source file column within line
  177. nextPlusLab   = 22  ;(4)   ;number for next "+" label
  178. prevMinusLab  = 26  ;(4)   ;number for previous "-" label
  179. address       = 30  ;(4)   ;current memory address for code assembly
  180. hashVal       = 34  ;(2)   ;16-bit hash value result
  181. hashPtr       = 36  ;(2)   ;pointer to selected entry in identifier hash table
  182. idPtr         = 38  ;(4)   ;pointer to current identifier descriptor
  183. idVal         = 42  ;(4)   ;value of current identifier
  184. varPtr        = 46  ;(4)   ;pointer to current identifier to be defined
  185. filePtr       = 50  ;(4)   ;pointer to current file info descriptor
  186. idType        = 54  ;(1)   ;type of current identifier (value,address,unres)
  187. originSet     = 55  ;(1)   ;flag indicating whether origin has been set
  188. expPlusCount  = 56  ;(1)   ;number of plus monadic operators of an operand
  189. expMinusCount = 57  ;(1)   ;number of minus monadic operators of an operand
  190. expLessCount  = 58  ;(1)   ;number of low-byte monadic operators of an operand
  191. expGreaterCount = 59 ;(1)  ;number of high-byte monadic operators of an operand
  192. expOffset     = 60  ;(1)   ;offset of cur operand in an expression descriptor
  193. expPtr        = 62  ;(4)   ;pointer to expression descriptor in far memory
  194. addressOrigin = 66  ;(4)   ;origin as set by org directive
  195. holeCount     = 70  ;(4)   ;number of holes (unresolved references)
  196. relHoleCount  = 74  ;(4)   ;number of holes for relative (internal) references
  197. instrNum      = 78  ;(1)   ;assem instr: instruction number (1-56)
  198. instrAddrMode = 79  ;(1)   ;assem instr: addressing mode for instr (1-12)
  199. instrValue    = 80  ;(2)   ;assem instr: operand value for instr (8/16 bit)
  200. instrValueType = 82 ;(1)   ;assem instr: operand value type
  201. instrOpcode   = 83  ;(1)   ;assem instr: opcode of instr/addrmode
  202. instrLen      = 84  ;(1)   ;assem instr: length of instruction
  203. memBufPage    = 85  ;(1)   ;mem put: page of buffer
  204. memBufPtr     = 86  ;(4)   ;mem put: pointer to 1K memory-buffer block
  205. memPutVals    = 90  ;(4)   ;mem put: values to put into memory
  206. memPutCount   = 94  ;(1)   ;mem put: number of values to put into memory
  207. memPutPage    = 95  ;(1)   ;mem put: current page for values
  208. newLine       = 96  ;(4)   ;current input line
  209. newCol        = 100 ;(1)   ;current input column
  210. arg           = 102 ;(2)   ;current command line argument
  211. reserved      = 104
  212. memWork       = 112 ;(16)  ;work area for the memory routines/low-level work
  213. strDelimit    = 112 ;(1)   ;string tokenize: delimiter--overlap
  214. numBase       = 113 ;(1)   ;number tokenize: base--overlap
  215. numSave       = 114 ;(4)   ;number tokenize: save--overlap
  216. work          = 112 ;(16)  ;miscellaneous work--low-level--overlap
  217.  
  218. hashTablePages = 16
  219. hashTableEntriesHigh = 4
  220. hashTableMask  = $03
  221. symNew = $81
  222. symUnresolved = $80
  223. symFound = 0
  224.  
  225. tokenIdentifier = 0
  226. tokenNumber  = 1
  227. tokenString  = 2
  228. tokenSpecial = 3
  229. tokenEOF     = 4
  230.  
  231. chrCR = $0d
  232. chrQuote = $22
  233. chrTab = $09
  234. chrEOF = $00
  235.  
  236. errOk            = 0       ;ok
  237. errIdentTooLong  = 1       ;an identifier token exceeds 240 chars in length
  238. errStringTooLong = 2       ;a string literal exceeds 255 chars in length
  239. errNoCloseQuote  = 3       ;ran into a CR before end of string literal
  240. errBadNumber     = 4       ;invalid numeric literal
  241. errNumOverflow   = 5       ;numeric literal value overflows 32-bits
  242. errSyntax        = 6       ;syntax error
  243. errInvalStrOpers = 7       ;attempt to perform numeric operators on a string
  244. errTooManyOperands = 8     ;expression has more than 17 operands
  245. errInsufficientMemory = 9  ;ran out of memory during compilation process
  246. errRedefinedSymbol = 10    ;attempt to redefine a symbol
  247. errOriginNotSet  = 11      ;attempt to assemble code with code origin not set
  248. errInternAssign  = 12      ;internal error: attempt to assign to unexpected id
  249. errNonNumIdExpr  = 13      ;non-numeric symbol in a numeric expression
  250. errExpectOperator = 14     ;expecting an operator
  251. errExpectOperand = 15      ;expecting an operand
  252. errExpectCommand = 16      ;expecting a command
  253. errValueTooLarge = 17      ;value is too large for operation (or is negative)
  254. errBranchTooFar  = 18      ;branch out of range
  255. errNotImplemented = 19     ;feature is not (yet) implemented
  256. errWrongAdmode   = 20      ;instruction does not support given address mode
  257. errAddressWrap   = 21      ;address wraped around 64K code address space
  258. errObjectFile    = 22      ;error trying to write output object file
  259. errNotResolvedExpr = 23    ;directive requires resolved expression
  260. errOriginAlreadySet = 24   ;code origin already set; you can't set it twice
  261. errUnresdReferences = 25   ;unresolved reference
  262. errDotCommand    = 26      ;this assembler doesn't accept dot commands
  263.  
  264. debug      : buf 1  ;display debug information: $ff=yes, $00=no
  265. symDump    : buf 1  ;display symbol table dump: $ff=yes, $00=no
  266. outputType : buf 1  ;type of output module: $00=binary, $01=reloc, $80=link
  267.  
  268. ;======== main routine ========
  269.  
  270. main = *
  271.    ;** check for large enough TPA
  272.    sec
  273.    lda #<bssEnd
  274.    cmp aceMemTop+0
  275.    lda #>bssEnd
  276.    sbc aceMemTop+1
  277.    bcs +
  278.    jmp mainCont
  279. +  lda #<tpaMsg
  280.    ldy #>tpaMsg
  281.    jsr eputs
  282. die = *
  283.    lda #1
  284.    ldx #0
  285.    jmp exit
  286.  
  287. tpaMsg = *
  288.    db "as: Insufficient program space to run in"
  289.    db chrCR,0
  290.  
  291. usage = *
  292.    lda #<usageMsg
  293.    ldy #>usageMsg
  294.    jsr eputs
  295.    jmp die
  296.  
  297. usageMsg = *
  298.    db "usage: as [-help] [-s] [-d] [file ...]"
  299.    db chrCR,chrCR
  300.    db "       -help : produce this information, don't run"
  301.    db chrCR
  302.    db "          -s : produce symbol table dump at end"
  303.    db chrCR
  304.    db "          -d : provide debugging information (lots)"
  305.    db chrCR,0
  306.  
  307. defaultInput = *
  308.    db "-stdin-"
  309.    db 0
  310.  
  311. filenameUsed : buf 1
  312.  
  313. mainCont = *
  314.    ;** init globals
  315.    lda #$00
  316.    sta debug        ;default off
  317.    sta symDump      ;default none
  318.    sta outputType   ;default binary
  319.    lda #$00
  320.    sta filenameUsed
  321.    lda #0
  322.    sta arg+0
  323.    sta arg+1
  324.    jsr asInit
  325.    ldx #7
  326. -  lda writeDefaultName,x
  327.    sta writeName,x
  328.    dex
  329.    bpl -
  330.  
  331.    mainNext = *
  332.    jsr checkStop
  333.    inc arg+0
  334.    bne +
  335.    inc arg+1
  336. +  lda arg+0
  337.    ldy arg+1
  338.    jsr getarg
  339.    lda zp+0
  340.    ora zp+1
  341.    beq mainExit
  342.    lda zp+0
  343.    ldy zp+1
  344.    sta name+0
  345.    sty name+1
  346.    ldy #0
  347.    lda (zp),y
  348.    cmp #"-"
  349.    bne +
  350.    jsr handleFlags
  351.    jmp mainNext
  352. +  jsr echo
  353.    jsr mainFile
  354.    jmp mainNext
  355.  
  356. mainExit = *
  357.    bit filenameUsed
  358.    bmi +
  359.    lda #<defaultInput
  360.    ldy #>defaultInput
  361.    sta name+0
  362.    sty name+1
  363.    jsr echo
  364.    jsr mainStdin
  365. +  lda #$00
  366.    ldx #3
  367. -  ora holeCount
  368.    dex
  369.    bpl -
  370.    cmp #$00
  371.    beq +
  372.    jsr findUnresSymbol
  373.    lda #errUnresdReferences
  374.    jmp errorRef
  375. +  jsr writeObjectFile
  376.    jsr dumpSymbolTable
  377.    rts
  378.  
  379. handleFlags = *
  380.    iny
  381.    lda (zp),y
  382.    bne +
  383.    rts
  384. +  cmp #"s"
  385.    beq flagS
  386.    cmp #"d"
  387.    beq flagD
  388.    jmp usage
  389.  
  390. flagS = *
  391.    lda #$ff
  392.    sta symDump
  393.    jmp handleFlags
  394.  
  395. flagD = *
  396.    lda #$ff
  397.    sta debug
  398.    jmp handleFlags
  399.  
  400. echo = *
  401.    lda #<echoMsg1
  402.    ldy #>echoMsg1
  403.    jsr eputs
  404.    jsr echoName
  405.    lda #<echoMsg2
  406.    ldy #>echoMsg2
  407.    jmp eputs
  408. echoName = *
  409.    lda name+0
  410.    ldy name+1
  411.    jmp eputs
  412.  
  413. echoMsg1 = *
  414.    db "assembling source file "
  415.    db chrQuote,0
  416. echoMsg2 = *
  417.    db chrQuote,chrCR,0
  418.  
  419. mainFile = *
  420.    bit filenameUsed
  421.    bmi +
  422.    jsr mainExtractObj
  423. +  lda name+0
  424.    ldy name+1
  425.    sta zp+0
  426.    sty zp+1
  427.    lda #"r"
  428.    jsr open
  429.    bcc +
  430.    jsr echoName
  431.    lda #<mainFileErr
  432.    ldy #>mainFileErr
  433.    jsr eputs
  434.    jmp die
  435. +  sta sourceFcb
  436.    jsr asDriver
  437.    lda sourceFcb
  438.    jsr close
  439.    lda #$ff
  440.    sta filenameUsed
  441.    rts
  442. mainFileErr = *
  443.    db ": Cannot open file"
  444.    db chrCR,0
  445.  
  446. mainStdin = *
  447.    lda #stdin
  448.    sta sourceFcb
  449.    jsr asDriver
  450.    rts
  451.  
  452. mainExtractObj = *
  453.    ldx #0 ;copy-start
  454.    ldy #0
  455. -  lda (name),y
  456.    beq +++
  457.    cmp #":"
  458.    beq +
  459.    cmp #"/"
  460.    bne ++
  461. +  tya
  462.    tax
  463.    inx
  464. +  iny
  465.    bne -
  466. +  txa
  467.    tay
  468.    ldx #0
  469. -  lda (name),y
  470.    sta stringBuf,x
  471.    beq +
  472.    iny
  473.    inx
  474.    bne -
  475. +  nop
  476. -  cpx #3
  477.    bcs +
  478.    rts
  479. +  lda stringBuf-2,x
  480.    cmp #","
  481.    bne +
  482.    lda #0
  483.    dex
  484.    dex
  485.    sta stringBuf,x
  486.    jmp -
  487. +  cmp #"."
  488.    beq +
  489.    rts
  490. +  lda stringBuf-1,x
  491.    cmp #"s"
  492.    beq +
  493.    rts
  494. +  cpx #18
  495.    bcc +
  496.    ldx #18
  497. +  lda #","
  498.    sta stringBuf-2,x
  499.    lda #"p"
  500.    sta stringBuf-1,x
  501.    lda #0
  502.    sta stringBuf,x
  503. -  lda stringBuf,x
  504.    sta writeName,x
  505.    dex
  506.    bpl -
  507.    rts
  508.  
  509. asInit = *  ;initialize variables for assembly
  510.    ldx #3
  511.    lda #0
  512. -  sta newLine,x
  513.    sta nextPlusLab,x
  514.    sta prevMinusLab,x
  515.    sta address,x
  516.    sta holeCount,x
  517.    sta relHoleCount,x
  518.    dex
  519.    bpl -
  520.    sta newCol
  521.    lda #1
  522.    sta newLine+0
  523.    sta nextPlusLab+0
  524.    lda #$00
  525.    sta originSet
  526.    lda #<$1300
  527.    ldy #>$1300
  528.    sta address+0
  529.    sty address+1
  530.    sta addressOrigin+0
  531.    sty addressOrigin+1
  532.    jsr mallocInit
  533.    jsr initSymbolTable
  534.    jsr memInit
  535.    rts
  536.  
  537. ;======== driver ========
  538.  
  539. asDriver = *
  540.    lda #$ff
  541.    sta bufptr
  542.    lda #" "
  543.    sta prevChar
  544. -  jsr parse
  545.    bcc -
  546.    rts
  547.  
  548. writeObTry : buf 1
  549. writeObFd  : buf 1
  550.  
  551. writeObjectFile = *
  552.    lda #<writeMsg
  553.    ldy #>writeMsg
  554.    jsr eputs
  555.    lda #<writeName
  556.    ldy #>writeName
  557.    jsr eputs
  558.    lda #chrQuote
  559.    ldx #stderr
  560.    jsr putc
  561.    ldx #stderr
  562.    lda #chrCR
  563.    jsr putc
  564.    lda #2
  565.    sta writeObTry
  566.    lda #<writeName
  567.    ldy #>writeName
  568.    sta zp+0
  569.    sty zp+1
  570.  
  571.    ;** open object for writing
  572. -  lda #"w"
  573.    jsr open
  574.    bcc ++
  575.    lda errno
  576.    cmp #aceErrFileExists
  577.    beq +
  578. -  lda #errObjectFile
  579.    jmp error
  580. +  dec writeObTry
  581.    beq -
  582.    jsr remove
  583.    bcs -
  584.    jmp --
  585. +  sta writeObFd
  586.  
  587.    ;** write object data
  588.    lda addressOrigin+0
  589.    ldx writeObFd
  590.    jsr putc
  591.    lda addressOrigin+1
  592.    ldx writeObFd
  593.    jsr putc
  594.    lda writeObFd
  595.    ldx addressOrigin+0
  596.    ldy addressOrigin+1
  597.    jsr memSave
  598.  
  599.    ;** close object
  600.    lda writeObFd
  601.    jsr close
  602.    bcc +
  603.    lda #errObjectFile
  604.    jmp error
  605. +  lda #<writeRangeMsg1
  606.    ldy #>writeRangeMsg1
  607.    jsr eputs
  608.    lda addressOrigin+1
  609.    ldx #stderr
  610.    jsr fputhex
  611.    lda addressOrigin+0
  612.    ldx #stderr
  613.    jsr fputhex
  614.    lda #<writeRangeMsg2
  615.    ldy #>writeRangeMsg2
  616.    jsr eputs
  617.    sec 
  618.    lda address+0
  619.    sbc #1
  620.    pha
  621.    lda address+1
  622.    sbc #0
  623.    ldx #stderr
  624.    jsr fputhex
  625.    pla
  626.    ldx #stderr
  627.    jsr fputhex
  628.    lda #<writeRangeMsg3
  629.    ldy #>writeRangeMsg3
  630.    jsr eputs
  631.    sec
  632.    lda address+0
  633.    sbc addressOrigin+0
  634.    sta work+0
  635.    lda address+1
  636.    sbc addressOrigin+1
  637.    sta work+1
  638.    lda #0
  639.    sta work+2
  640.    sta work+3
  641.    ldx #work
  642.    jsr eputnum
  643.    lda #<writeRangeMsg4
  644.    ldy #>writeRangeMsg4
  645.    jsr eputs
  646.    rts
  647.  
  648. writeDefaultName = *
  649.    db "a.out,p"
  650.    db 0
  651. writeMsg = *
  652.    db "writing object file "
  653.    db chrQuote,0
  654. writeRangeMsg1 = *
  655.    db "code range: $"
  656.    db 0
  657. writeRangeMsg2 = *
  658.    db "--$"
  659.    db 0
  660. writeRangeMsg3 = *
  661.    db " ("
  662.    db 0
  663. writeRangeMsg4 = *
  664.    db " bytes)"
  665.    db chrCR,0
  666.  
  667. ;======== parser ========
  668.  
  669. parse = *
  670.    ;** at beginning of command
  671.    jsr checkStop
  672.    jsr getToken
  673.    lda tokenType
  674.    cmp #tokenEOF
  675.    bne +
  676.    sec
  677.    rts
  678. +  cmp #tokenIdentifier
  679.    bne parseNotId
  680.    lda tokenNextChar
  681.    cmp #"="
  682.    bne +
  683.    jmp parseEquate
  684. +  cmp #":"
  685.    bne +
  686.    jmp parseAddress
  687. +  jmp parseIdentifier
  688.  
  689. parseNotId = *
  690.    cmp #tokenSpecial
  691.    beq +
  692.    syntaxError = *
  693.    lda #errSyntax
  694.    jmp error
  695. +  lda tokenChar
  696.    cmp #chrCR
  697.    bne +
  698.    jmp parseEnd
  699. +  cmp #"+"
  700.    bne +
  701.    jmp parsePlus
  702. +  cmp #"-"
  703.    bne +
  704.    jmp parseMinus
  705. +  cmp #"#"
  706.    bne +
  707.    jmp parseEnd
  708. +  cmp #"."
  709.    bne +
  710.    jmp parseDotCommand
  711. +  jmp syntaxError
  712.  
  713. ;ret: .X=tokenIdentifier, .A=nextChar, .Y=strlen, stringLen, stringBuf
  714. ;     .X=tokenNumber,     .Y=numlen, number
  715. ;     .X=tokenString,     .A=firstChar,.Y=strlen, stringLen, stringBuf
  716. ;     .X=tokenSpecial,    .A=char
  717.  
  718. parseEquate = *
  719.    jsr parseDefineVar
  720.    jsr getToken
  721.    cpx #tokenSpecial
  722.    beq +
  723. -  jmp syntaxError
  724. +  cmp #"="
  725.    bne -
  726.    lda #0
  727.    jsr parseExpression
  728.    cmp #chrCR
  729.    bne -
  730.    jsr evaluateExpression
  731.    bcs +
  732.    jsr assignVariable
  733.    jmp ++
  734. +  jsr addVariableHole
  735. +  bit debug
  736.    bpl +
  737.    lda #<parseEquateMsg
  738.    ldy #>parseEquateMsg
  739.    jsr puts
  740. +  jmp parseEnd
  741.    parseEquateMsg = *
  742.    db "parseEquate: assign parsed expression to variable."
  743.    db chrCR,0
  744.  
  745. parseAddress = *
  746.    jsr parseDefineVar
  747.    jsr getToken
  748.    cpx #tokenSpecial
  749.    beq +
  750. -  jmp syntaxError
  751. +  cmp #":"
  752.    beq +
  753.    jmp syntaxError
  754. +  jsr parseAssignAddress
  755.    bit debug
  756.    bpl +
  757.    lda #<parseAddressMsg
  758.    ldy #>parseAddressMsg
  759.    jsr puts
  760. +  jmp parseEnd
  761.    parseAddressMsg = *
  762.    db "parseAddress: assign current address to variable."
  763.    db chrCR,0
  764.  
  765. parseAssignAddress = *
  766.    bit originSet
  767.    bmi +
  768.    lda #errOriginNotSet
  769.    jmp error
  770. +  ldx #3
  771. -  lda address,x
  772.    sta idVal,x
  773.    dex
  774.    bpl -
  775.    lda #$01
  776.    sta idType
  777.    jmp assignVariable
  778.  
  779. parsePlus = *
  780.    lda #"+"
  781.    ldy #0
  782.    jsr genRelLabel
  783.    jsr parseDefineVar
  784.    jsr parseAssignAddress
  785.    bit debug
  786.    bpl +
  787.    lda #<parsePlusMsg
  788.    ldy #>parsePlusMsg
  789.    jsr puts
  790.    ldx #nextPlusLab
  791.    jsr putnum
  792.    lda #chrCR
  793.    jsr putchar
  794. +  inc nextPlusLab+0
  795.    bne +
  796.    inc nextPlusLab+1
  797.    bne +
  798.    inc nextPlusLab+2
  799.    bne +
  800.    inc nextPlusLab+3
  801. +  jmp parseEnd
  802.    parsePlusMsg = *
  803.    db "parsePlus: assign current address to a syntheic '+' variable:"
  804.    db 0
  805.  
  806. parseMinus = *
  807.    inc prevMinusLab+0
  808.    bne +
  809.    inc prevMinusLab+1
  810.    bne +
  811.    inc prevMinusLab+2
  812.    bne +
  813.    inc prevMinusLab+3
  814. +  lda #"-"
  815.    ldy #0
  816.    jsr genRelLabel
  817.    jsr parseDefineVar
  818.    jsr parseAssignAddress
  819.    bit debug
  820.    bpl +
  821.    lda #<parseMinusMsg
  822.    ldy #>parseMinusMsg
  823.    jsr puts
  824.    ldx #prevMinusLab
  825.    jsr putnum
  826.    lda #chrCR
  827.    jsr putchar
  828. +  jmp parseEnd
  829.    parseMinusMsg = *
  830.    db "parseMinus: assign current address to a synthetic '-' variable:"
  831.    db 0
  832.  
  833. genRelLabel = *  ;( .A=type, .Y=relative )
  834.    sta stringBuf+1
  835.    cmp #"+"
  836.    bne +
  837.    clc
  838.    tya
  839.    adc nextPlusLab
  840.    sta number+0
  841.    ldy #3
  842.    ldx #1
  843. -  lda nextPlusLab,x
  844.    adc #0
  845.    sta number,x
  846.    inx
  847.    dey
  848.    bne -
  849.    jmp ++
  850. +  sec
  851.    sty number+0
  852.    lda prevMinusLab+0
  853.    sbc number+0
  854.    sta number+0
  855.    ldy #3
  856.    ldx #1
  857. -  lda prevMinusLab,x
  858.    sbc #0
  859.    sta number,x
  860.    inx
  861.    dey
  862.    bne -
  863. +  lda #"L"
  864.    sta stringBuf+0
  865.    lda #<stringBuf+2
  866.    ldy #>stringBuf+2
  867.    sta zp+0
  868.    sty zp+1
  869.    ldx #number
  870.    lda #1
  871.    jsr utoa
  872.    iny
  873.    iny
  874.    lda #"c"
  875.    sta stringBuf,y
  876.    iny
  877.    lda #0
  878.    sta stringBuf,y
  879.    sty stringLen
  880.    rts
  881.  
  882. parseEnd = *
  883.    bit debug
  884.    bpl +
  885.    lda #<parseEndMsg
  886.    ldy #>parseEndMsg
  887.    jsr puts
  888. +  clc
  889.    rts
  890.    parseEndMsg = *
  891.    db "-----=-----"
  892.    db chrCR,chrCR,0
  893.  
  894. parseIdentifier = *  ;line starting with an identifier
  895.    jsr hash
  896.    ;** check if identifier is a processor instruction
  897.    lda stringLen
  898.    cmp #3
  899.    bne parseIdNotInstr
  900.    lda hashVal+0
  901.    and #63
  902.    tax
  903.    lda instrHashPtrs,x
  904.    cmp #100
  905.    bcs +
  906.    jsr parseIdCheckInstr
  907.    bcs parseIdNotInstr
  908.    jmp instr
  909. +  sec
  910.    sbc #100
  911.    tax
  912. -  lda instrHashIndirects,x
  913.    beq parseIdNotInstr
  914.    jsr parseIdCheckInstr
  915.    bcs +
  916.    jmp instr
  917. +  inx
  918.    bne -
  919.  
  920.    ;** check if identifier is a directive
  921.    parseIdNotInstr = *
  922.    jsr checkIfDirective
  923.    bcs parseIdNotDirective
  924.    jmp directive
  925.  
  926.    ;** check if identifier is a macro
  927.    parseIdNotDirective = *
  928.    lda #errExpectCommand
  929.    jmp error
  930.  
  931. parseDotCommand = *
  932.    lda #errDotCommand
  933.    jmp error
  934.  
  935. ;======== handle assembler directives ========
  936.  
  937. direcNum : buf 1
  938.  
  939. checkIfDirective = *  ;( stringBuf, stringLen ) : .CS=no, .A=dirNum
  940.    lda #0
  941.    sta direcNum
  942.  
  943.    direcCheckNext = *
  944.    ldx direcNum
  945.    ldy direcOffsets,x
  946.    ldx #0
  947. -  lda stringBuf,x
  948.    cmp direcNames,y
  949.    bne direcCheckCont
  950.    cmp #$00
  951.    bne +
  952.    lda direcNum
  953.    clc
  954.    rts
  955. +  iny
  956.    inx
  957.    bne -
  958.  
  959.    direcCheckCont = *
  960.    inc direcNum
  961.    lda direcNum
  962.    cmp #16
  963.    bcc direcCheckNext
  964.    lda #0
  965.    sec
  966.    rts
  967.  
  968. direcOffsets = *
  969.    db 00,03,07,10,13,16,20,28,31,37,42,48,54,63,70
  970.  
  971. direcNames = *
  972.    db "db"       ;dn=01.  off=00
  973.    db 0
  974.    db "buf"      ;dn=02.  off=03
  975.    db 0
  976.    db "dw"       ;dn=03.  off=07
  977.    db 0
  978.    db "dt"       ;dn=04.  off=10
  979.    db 0
  980.    db "dl"       ;dn=05.  off=13
  981.    db 0
  982.    db "org"      ;dn=06.  off=16
  983.    db 0
  984.    db "include"  ;dn=07.  off=20
  985.    db 0
  986.    db "if"       ;dn=08.  off=28
  987.    db 0
  988.    db "elsif"    ;dn=09.  off=31
  989.    db 0
  990.    db "else"     ;dn=10.  off=37
  991.    db 0
  992.    db "endif"    ;dn=11.  off=42
  993.    db 0
  994.    db "macro"    ;dn=12.  off=48
  995.    db 0
  996.    db "endmacro" ;dn=13.  off=54
  997.    db 0
  998.    db "export"   ;dn=14.  off=63
  999.    db 0
  1000.    db "bss"      ;dn=15.  off=70
  1001.    db 0
  1002.  
  1003. direcVectors = *
  1004.    dw direcDb,direcBuf,direcDw,direcDt,direcDl,direcOrg,direcInclude
  1005.    dw direcIf,direcElsif,direcElse,direcEndif,direcMacro,direcEndmacro
  1006.    dw direcExport,direcBss
  1007.  
  1008. directive = *  ;( .A=dirNum )
  1009.    bit debug
  1010.    bpl +
  1011.    pha
  1012.    lda #<direcMsg
  1013.    ldy #>direcMsg
  1014.    jsr puts
  1015.    pla
  1016. +  asl
  1017.    tay
  1018.    lda direcVectors+0,y
  1019.    sta work+14
  1020.    lda direcVectors+1,y
  1021.    sta work+15
  1022.    jsr +
  1023.    jmp parseEnd
  1024. +  jmp (work+14)
  1025.    direcMsg = *
  1026.    db "must parse a directive"
  1027.    db chrCR,0
  1028.  
  1029. direcOrg = *
  1030.    bit originSet
  1031.    bpl +
  1032.    lda #errOriginAlreadySet
  1033.    jmp error
  1034. +  lda #0
  1035.    jsr parseExpression
  1036.    cmp #chrCR
  1037.    beq +
  1038.    jmp syntaxError
  1039. +  jsr evaluateExpression
  1040.    bcc +
  1041.    lda #errNotResolvedExpr
  1042.    jmp error
  1043. +  lda idVal+2
  1044.    ora idVal+3
  1045.    beq +
  1046.    lda #errValueTooLarge
  1047.    jmp error
  1048. +  lda idVal+0
  1049.    ldy idVal+1
  1050.    sta address+0
  1051.    sty address+1
  1052.    sta addressOrigin+0
  1053.    sty addressOrigin+1
  1054.    lda #$ff
  1055.    sta originSet
  1056.    bit debug
  1057.    bpl +
  1058.    lda #<direcOrgMsg
  1059.    ldy #>direcOrgMsg
  1060.    jsr puts
  1061.    lda idVal+1
  1062.    jsr puthex
  1063.    lda idVal+0
  1064.    jsr puthex
  1065.    lda #chrCR
  1066.    jsr putchar
  1067. +  rts
  1068.    direcOrgMsg = *
  1069.    db "setting code origin to $"
  1070.    db 0
  1071.  
  1072. direcDfSize : buf 1
  1073. direcDfChar : buf 1
  1074.  
  1075. direcDb = *
  1076.    lda #1
  1077.    bne direcDlIn
  1078. direcDw = *
  1079.    lda #2
  1080.    bne direcDlIn
  1081. direcDt = *
  1082.    lda #3
  1083.    bne direcDlIn
  1084. direcDl = *
  1085.    lda #4
  1086.    direcDlIn = *
  1087.    sta direcDfSize
  1088.    bit originSet
  1089.    bmi direcDfNext
  1090.    lda #errOriginNotSet
  1091.    jmp error
  1092.  
  1093.    direcDfNext = *
  1094.    lda #1
  1095.    jsr parseExpression
  1096.    sta direcDfChar
  1097.    cpx #0
  1098.    beq +
  1099.    jsr direcDfString
  1100.    jmp direcDfCont
  1101. +  jsr evaluateExpression
  1102.    bcs ++
  1103.    ldx direcDfSize
  1104. -  cpx #4
  1105.    bcs ++
  1106.    lda idVal,x
  1107.    bne +
  1108.    inx
  1109.    bne -
  1110. +  lda #errValueTooLarge
  1111.    jmp error
  1112. +  lda #1
  1113.    ldy #0
  1114.    sta direcDfCount+0
  1115.    sty direcDfCount+1
  1116.    jsr direcDfPut
  1117.  
  1118.    direcDfCont = *
  1119.    lda direcDfChar
  1120.    cmp #","
  1121.    beq direcDfNext
  1122.    cmp #chrCR
  1123.    beq +
  1124.    jmp syntaxError
  1125. +  rts
  1126.  
  1127. direcDfStrPos : buf 1
  1128.  
  1129. direcDfString = *
  1130.    lda #0
  1131.    sta direcDfStrPos
  1132.    sta idType
  1133.    sta idVal+1
  1134.    sta idVal+2
  1135.    sta idVal+3
  1136. -  ldx direcDfStrPos
  1137.    cpx stringLen
  1138.    bcc +
  1139.    rts
  1140. +  lda stringBuf,x
  1141.    sta idVal+0
  1142.    lda #1
  1143.    ldy #0
  1144.    sta direcDfCount+0
  1145.    sty direcDfCount+1
  1146.    jsr direcDfPut
  1147.    inc direcDfStrPos
  1148.    jmp -
  1149.  
  1150. direcDfCount : buf 2
  1151.  
  1152. direcDfPut = *  ;(address++, idVal, idType, direcDfSize, direcDfCount--, expBuf)
  1153.    lda direcDfCount+0
  1154.    ora direcDfCount+1
  1155.    bne +
  1156.    rts
  1157.  
  1158.    ;** debug information
  1159. +  bit debug
  1160.    bpl +++
  1161.    lda #<direcDfPutMsg1
  1162.    ldy #>direcDfPutMsg1
  1163.    jsr puts
  1164.    lda address+1
  1165.    jsr puthex
  1166.    lda address+0
  1167.    jsr puthex
  1168.    lda #<direcDfPutMsg2
  1169.    ldy #>direcDfPutMsg2
  1170.    jsr puts
  1171.    bit idType
  1172.    bpl +
  1173.    lda #"?"
  1174.    jsr putchar
  1175.    jmp ++
  1176. +  ldx #idVal
  1177.    jsr putnum
  1178. +  lda #chrCR
  1179.    jsr putchar
  1180.  
  1181.    ;** handle unresolved reference
  1182. +  bit idType
  1183.    bpl +
  1184.    ldx direcDfSize
  1185.    lda #0
  1186.    jsr addMemoryHole
  1187.  
  1188.    ;** handle resolved reference
  1189. +  ldx #3
  1190. -  lda idVal,x
  1191.    sta memPutVals,x
  1192.    dex
  1193.    bpl -
  1194.    lda direcDfSize
  1195.    ldx address+0
  1196.    ldy address+1
  1197.    jsr memPut
  1198.    ;** add relocatable reference
  1199.    lda idType
  1200.    beq +
  1201.    cmp #$04
  1202.    bcs +
  1203.    ldx address+0
  1204.    ldy address+1
  1205.    jsr recordRelocRef
  1206.  
  1207.    ;** go onto next put
  1208. +  clc
  1209.    lda address+0
  1210.    adc direcDfSize
  1211.    sta address+0
  1212.    bcc +
  1213.    inc address+1
  1214.    bne +
  1215.    lda #errAddressWrap
  1216.    jmp error
  1217. +  lda direcDfCount+0
  1218.    bne +
  1219.    dec direcDfCount+1
  1220. +  dec direcDfCount+0
  1221.    jmp direcDfPut
  1222.  
  1223. direcDfPutMsg1 = *
  1224.    db "define-put: address=$"
  1225.    db 0
  1226. direcDfPutMsg2 = *
  1227.    db ", value="
  1228.    db 0
  1229.  
  1230. direcBuf = *
  1231.    bit originSet
  1232.    bmi +
  1233.    lda #errOriginNotSet
  1234.    jmp error
  1235. +  lda #0
  1236.    jsr parseExpression
  1237.    cmp #chrCR
  1238.    beq +
  1239.    jmp syntaxError
  1240. +  jsr evaluateExpression
  1241.    bcc +
  1242.    lda #errNotResolvedExpr
  1243.    jmp error
  1244. +  lda idVal+2
  1245.    ora idVal+3
  1246.    beq +
  1247.    lda #errValueTooLarge
  1248.    jmp error
  1249. +  lda idVal+0
  1250.    ldy idVal+1
  1251.    sta direcDfCount+0
  1252.    sty direcDfCount+1
  1253. +  lda #0
  1254.    sta idType
  1255.    sta idVal+0
  1256.    sta idVal+1
  1257.    sta idVal+2
  1258.    sta idVal+3
  1259.    lda #1
  1260.    sta direcDfSize
  1261.    jsr direcDfPut
  1262.    rts
  1263.  
  1264. direcInclude = *
  1265. direcIf = *
  1266. direcElsif = *
  1267. direcElse = *
  1268. direcEndif = *
  1269. direcMacro = *
  1270. direcEndmacro = *
  1271. direcExport = *
  1272.    lda #errNotImplemented
  1273.    jmp error
  1274. direcBss = *
  1275.    bit originSet
  1276.    bpl +
  1277.    lda #errOriginNotSet
  1278.    jmp error
  1279. +  nop
  1280.    lda #errNotImplemented
  1281.    jmp error
  1282.  
  1283. ;======== error handler ========
  1284.  
  1285. errorCode      : buf 1
  1286. errorPos       : buf 1
  1287. errorExitCode  = aceExitData+0    ;$fc8a09cb:editor-repos
  1288. errorExitLine  = aceExitData+4
  1289. errorExitCol   = aceExitData+8
  1290. errorExitRepos = aceExitData+12
  1291. errorExitFilep = aceExitData+13
  1292. errorExitReser = aceExitData+14
  1293. errorBuf       = aceExitData+15
  1294.  
  1295. errorRef = *
  1296.    jsr errorPreramble
  1297.    lda #<errorMsg2
  1298.    ldy #>errorMsg2
  1299.    jsr errorCat
  1300.    ldx #3
  1301. -  lda expSrcLine,x
  1302.    sta work+0,x
  1303.    lda expSrcFile,x
  1304.    sta work+4,x
  1305.    dex
  1306.    bpl -
  1307.    lda expSrcCol
  1308.    ldx #work+0
  1309.    ldy #work+4
  1310.    jsr errorDispFile
  1311.    jmp errorIn
  1312.  
  1313. errorPreramble = *
  1314.    sta errorCode
  1315.    ldx #14
  1316. -  lda errorExitHead,x
  1317.    sta errorExitCode,x
  1318.    dex
  1319.    bpl -
  1320.    lda #0
  1321.    sta errorPos
  1322.    lda #<errorMsg1
  1323.    ldy #>errorMsg1
  1324.    jsr errorCat
  1325.    ldx #sourceLine
  1326.    ldy #filePtr
  1327.    lda sourceCol
  1328.    jmp errorDispFile
  1329.  
  1330. error = *
  1331.    jsr errorPreramble
  1332.    errorIn = *
  1333.    ldx errorPos
  1334.    lda #" "
  1335.    sta errorBuf,x
  1336.    inc errorPos
  1337.    lda errorCode
  1338.    asl
  1339.    tax
  1340.    lda errDesc+1,x
  1341.    tay
  1342.    lda errDesc+0,x
  1343.    jsr errorCat
  1344.    lda errorCode
  1345.    cmp #errUnresdReferences
  1346.    bne +
  1347.    lda #<symName
  1348.    ldy #>symName
  1349.    jsr errorCat
  1350. +  lda #<errorBuf
  1351.    ldy #>errorBuf
  1352.    jsr eputs
  1353.    lda #chrCR
  1354.    ldx #stderr
  1355.    jsr putc
  1356.    lda #1
  1357.    ldx #0
  1358.    jmp exit
  1359.  
  1360. errDispFiFp  : buf 1
  1361. errDispFiCol : buf 1
  1362. errDispFiLin : buf 1
  1363.  
  1364. errorDispFile = *  ;( .X=zpLineOff, .A=col, .Y=zpFilePtr, errorPos ) : errorPos
  1365.    ;** uses name instead of filePtr for now
  1366.    ;** produces output of the form: ("filename":1234:12)
  1367.    sta errDispFiCol
  1368.    stx errDispFiLin
  1369.    sty errDispFiFp
  1370.    ldx errorPos
  1371.    lda #"("
  1372.    sta errorBuf,x
  1373.    inx
  1374.    lda #chrQuote
  1375.    sta errorBuf,x
  1376.    inx
  1377.    stx errorPos
  1378.    lda name+0
  1379.    ldy name+1
  1380.    jsr errorCat
  1381.    lda #chrQuote
  1382.    sta errorBuf,x
  1383.    inx
  1384.    lda #":"
  1385.    sta errorBuf,x
  1386.    inx
  1387.    stx errorPos
  1388.    ldx errDispFiLin
  1389.    jsr errorDispFileApnum
  1390.    lda #":"
  1391.    sta errorBuf,x
  1392.    inx
  1393.    stx errorPos
  1394.    lda errDispFiCol
  1395.    sta number+0
  1396.    lda #0
  1397.    sta number+1
  1398.    sta number+2
  1399.    sta number+3
  1400.    ldx #number
  1401.    jsr errorDispFileApnum
  1402.    lda #")"
  1403.    sta errorBuf,x
  1404.    inx
  1405.    stx errorPos
  1406.    rts
  1407.  
  1408. errorDispFileApnum = *  ;( .X=zpoff, errorPos ) : .X=errorPos
  1409.    lda #<putnumNum
  1410.    ldy #>putnumNum
  1411.    sta zp+0
  1412.    sty zp+1
  1413.    lda #1
  1414.    jsr utoa
  1415.    lda #<putnumNum
  1416.    ldy #>putnumNum
  1417.    ;** fall through
  1418.  
  1419. errorCat = *  ;( .AY=str, errorPos ) : .X=errorPos
  1420.    sta work+14
  1421.    sty work+15
  1422.    ldx errorPos
  1423.    ldy #0
  1424. -  lda (work+14),y
  1425.    sta errorBuf,x
  1426.    beq +
  1427.    inx
  1428.    iny
  1429.    bne -
  1430. +  stx errorPos
  1431.    rts
  1432.  
  1433. errorExitHead = *
  1434.    db $fc,$8a,$09,$cb,$00,$00,$00,$00,$00,$00,$00,$00,$ff,$06,$00
  1435. errorMsg1 = *
  1436.    db "err "
  1437.    db 0
  1438. errorMsg2 = *
  1439.    db ", ref"
  1440.    db 0
  1441.  
  1442. errDesc: dw err00,err01,err02,err03,err04,err05,err06,err07,err08,err09
  1443.          dw err10,err11,err12,err13,err14,err15,err16,err17,err18,err19
  1444.          dw err20,err21,err22,err23,err24,err25,err26
  1445.  
  1446. err00: db "Ok--no error"
  1447.        db 0
  1448. err01: db "An identifier token exceeds 240 chars in length"
  1449.        db 0
  1450. err02: db "A string literal exceeds 240 chars in length"
  1451.        db 0
  1452. err03: db "Ran into a CR before end of string literal"
  1453.        db 0
  1454. err04: db "Invalid numeric literal"
  1455.        db 0
  1456. err05: db "Numeric literal value overflows 32-bits"
  1457.        db 0
  1458. err06: db "Syntax error"
  1459.        db 0
  1460. err07: db "Attempt to perform numeric operators on a string"
  1461.        db 0
  1462. err08: db "Expression has more than 17 operands"
  1463.        db 0
  1464. err09: db "Ran out of memory during compilation process"
  1465.        db 0
  1466. err10: db "Attempt to redefine a symbol"
  1467.        db 0
  1468. err11: db "Attempt to assemble code with code origin not set"
  1469.        db 0
  1470. err12: db "Internal error: attempt to assign to unexpected id"
  1471.        db 0
  1472. err13: db "Non-numeric symbol in a numeric expression"
  1473.        db 0
  1474. err14: db "Expecting an operator"
  1475.        db 0
  1476. err15: db "Expecting an operand"
  1477.        db 0
  1478. err16: db "Expecting a command"
  1479.        db 0
  1480. err17: db "Value is too large or negative"
  1481.        db 0
  1482. err18: db "Branch out of range"
  1483.        db 0
  1484. err19: db "Feature is not (yet) implemented"
  1485.        db 0
  1486. err20: db "Instruction does not support given address mode"
  1487.        db 0
  1488. err21: db "Address wraped around 64K code address space"
  1489.        db 0
  1490. err22: db "Error trying to write output object file"
  1491.        db 0
  1492. err23: db "Directive requires resolved expression"
  1493.        db 0
  1494. err24: db "Code origin already set; you can't set it twice"
  1495.        db 0
  1496. err25: db "Unresolved symbol: "
  1497.        db 0
  1498. err26: db "Thus assembler doesn't accept .dot commands, Buddy!"
  1499.        db 0
  1500.  
  1501. wputnum = *
  1502.    lda #stdout
  1503.    sta putnumFd
  1504.    jmp putnumIn
  1505. eputnum = *
  1506.    lda #stderr
  1507.    jmp fputnum
  1508. putnum = *
  1509.    lda #stdout
  1510. fputnum = *
  1511.    sta putnumFd
  1512.    ldy #1
  1513. putnumIn = *
  1514.    lda #<putnumNum
  1515.    sta zp+0
  1516.    lda #>putnumNum
  1517.    sta zp+1
  1518.    tya
  1519.    jsr utoa
  1520.    ldx putnumFd
  1521.    jmp fputsZp
  1522.  
  1523. putnumFd  : buf 1
  1524. putnumNum : buf 11
  1525.  
  1526. puthex = *  ;( .A=value )
  1527.    ldx #stdout
  1528. fputhex = *  ;( .A=value, .X=fd )
  1529.    stx putnumFd
  1530.    pha
  1531.    lsr
  1532.    lsr
  1533.    lsr
  1534.    lsr
  1535.    tax
  1536.    lda puthexChars,x
  1537.    ldx putnumFd
  1538.    jsr putc
  1539.    pla
  1540.    and #$0f
  1541.    tax
  1542.    lda puthexChars,x
  1543.    ldx putnumFd
  1544.    jsr putc
  1545.    rts
  1546.    puthexChars = *
  1547.    db "0123456789abcdef"
  1548.  
  1549. checkStop = *
  1550.    jsr stopkey
  1551.    bcs +
  1552.    rts
  1553. +  lda #<stoppedMsg
  1554.    ldy #>stoppedMsg
  1555.    jsr eputs
  1556.    lda #1
  1557.    ldx #0
  1558.    jmp exit
  1559.  
  1560.    stoppedMsg = *
  1561.    db "<Stopped>"
  1562.    db chrCR,0
  1563.  
  1564. ;======== utility functions ========
  1565.  
  1566. incLong = *  ;( .X=zpOffset )
  1567.    inc 0,x
  1568.    bne +
  1569.    inc 1,x
  1570.    bne +
  1571.    inc 2,x
  1572.    bne +
  1573.    inc 3,x
  1574. +  rts
  1575.  
  1576. decLong = *  ;( .X=zpOffset )
  1577.    sec
  1578.    lda 0,x
  1579.    sbc #1
  1580.    sta 0,x
  1581.    inx
  1582.    ldy #3
  1583. -  lda 0,x
  1584.    sbc #0
  1585.    sta 0,x
  1586.    inx
  1587.    dey
  1588.    bne -
  1589.    rts
  1590.  
  1591. ;======== included files ========
  1592.  
  1593. ;--> include ashelp.s
  1594. ;** assembler program utility file - by Craig Bruce - 26-Sep-1994
  1595.  
  1596. ;======== assemble processor instruction ========
  1597.  
  1598. ; num bkt ins     num bkt ins     num bkt ins     num bkt ins     num bkt ins
  1599. ; 00. xx. xxx     12. 63. bvc     24. 22. eor     36. 20. pha     48. 27. sta
  1600. ; 01. 12. adc     13. 15. bvs     25. 05. inc     37. 35. php     49. 50. stx
  1601. ; 02. 63. and     14. 38. clc     26. 26. inx     38. 40. pla     50. 51. sty
  1602. ; 03. 00. asl     15. 39. cld     27. 27. iny     39. 55. plp     51. 12. tax
  1603. ; 04. 00. bcc     16. 44. cli     28. 06. jmp     40. 20. rol     52. 13. tay
  1604. ; 05. 16. bcs     17. 57. clv     29. 38. jsr     41. 26. ror     53. 38. tsx
  1605. ; 06. 24. beq     18. 24. cmp     30. 28. lda     42. 10. rti     54. 08. txa
  1606. ; 07. 47. bit     19. 15. cpx     31. 51. ldx     43. 20. rts     55. 26. txs
  1607. ; 08. 56. bmi     20. 16. cpy     32. 52. ldy     44. 03. sbc     56. 45. tya
  1608. ; 09. 25. bne     21. 60. dec     33. 24. lsr     45. 50. sec
  1609. ; 10. 42. bpl     22. 17. dex     34. 52. nop     46. 51. sed
  1610. ; 11. 51. brk     23. 18. dey     35. 45. ora     47. 56. sei
  1611.  
  1612. instrNames = *  ;names of instruction, 3 chars each
  1613.    db "xxxadcandaslbccbcsbeqbitbmibnebplbrkbvcbvsclccldcliclvcmpcpxcpy"
  1614.    db "decdexdeyeorincinxinyjmpjsrldaldxldylsrnoporaphaphpplaplprolror"
  1615.    db "rtirtssbcsecsedseistastxstytaxtaytsxtxatxstya"
  1616.  
  1617. instrHashPtrs = *  ;pointers to instruction numbers or >=100=indirects
  1618.    ;bucketx0..x1..x2..x3..x4..x5..x6..x7..x8..x9
  1619.    db 100,000,000,044,000,025,028,000,054,000  ;buckets 00-09
  1620.    db 042,000,103,052,000,106,109,022,023,000  ;buckets 10-19
  1621.    db 112,000,024,000,116,009,120,124,030,000  ;buckets 20-29
  1622.    db 000,000,000,000,000,037,000,000,127,015  ;buckets 30-39
  1623.    db 038,000,010,000,016,131,000,007,000,000  ;buckets 40-49
  1624.    db 134,137,142,000,000,039,145,017,000,000  ;buckets 50-59
  1625.    db 021,000,000,148                          ;buckets 60-63
  1626.  
  1627. instrHashIndirects = *
  1628.    db 004,003,000     ;off=100, bucket=00, instrs=bcc,asl
  1629.    db 001,051,000     ;off=103, bucket=12, instrs=adc,tax
  1630.    db 019,013,000     ;off=106, bucket=15, instrs=cpx,bvs
  1631.    db 005,020,000     ;off=109, bucket=16, instrs=bcs,cpy
  1632.    db 043,036,040,000 ;off=112, bucket=20, instrs=rts,pha,rol
  1633.    db 006,018,033,000 ;off=116, bucket=24, instrs=beq,cmp,lsr
  1634.    db 026,041,055,000 ;off=120, bucket=26, instrs=inx,ror,txs
  1635.    db 048,027,000     ;off=124, bucket=27, instrs=sta,iny
  1636.    db 029,014,053,000 ;off=127, bucket=38, instrs=jsr,clc,tsx
  1637.    db 035,056,000     ;off=131, bucket=45, instrs=ora,tya
  1638.    db 049,045,000     ;off=134, bucket=50, instrs=stx,sec
  1639.    db 031,050,011,046,000;off=137,buck=51, instrs=ldx,sty,brk,sed
  1640.    db 032,034,000     ;off=142, bucket=52, instrs=ldy,nop
  1641.    db 008,047,000     ;off=145, bucket=56, instrs=bmi,sei
  1642.    db 002,012,000     ;off=148, bucket=63, instrs=and,bvc
  1643.  
  1644. parseIdCheckInstr = *  ;( .A=instrNumToCheck ) : .CS=notInstr, .A+.X:unch
  1645.    sta work
  1646.    asl
  1647.    adc work
  1648.    tay
  1649.    lda stringBuf+0
  1650.    cmp instrNames+0,y
  1651.    bne +
  1652.    lda stringBuf+1
  1653.    cmp instrNames+1,y
  1654.    bne +
  1655.    lda stringBuf+2
  1656.    cmp instrNames+2,y
  1657.    bne +
  1658.    clc
  1659.    lda work
  1660.    rts
  1661. +  sec
  1662.    rts
  1663.  
  1664. instr = *  ;( .A=instrNum )
  1665.    ;** got instruction number
  1666.    sta instrNum
  1667.    bit originSet
  1668.    bmi +
  1669.    lda #errOriginNotSet
  1670.    jmp error
  1671. +  bit debug
  1672.    bpl +
  1673.    sta number+0
  1674.    lda #0
  1675.    sta number+1
  1676.    sta number+2
  1677.    sta number+3
  1678.    lda #<instrMsg
  1679.    ldy #>instrMsg
  1680.    jsr puts
  1681.    ldx #number
  1682.    jsr putnum
  1683.    lda #chrCR
  1684.    jsr putchar
  1685.  
  1686.    ;** get addressing mode and value
  1687. +  jsr instrGetAddrMode
  1688.    bit debug
  1689.    bpl +++
  1690.    lda instrAddrMode
  1691.    sta number+0
  1692.    lda #0
  1693.    sta number+1
  1694.    sta number+2
  1695.    sta number+3
  1696.    lda #<instrAddrMsg1
  1697.    ldy #>instrAddrMsg1
  1698.    jsr puts
  1699.    ldx #number
  1700.    jsr putnum
  1701.    lda #<instrAddrMsg2
  1702.    ldy #>instrAddrMsg2
  1703.    jsr puts
  1704.    lda instrValue+0
  1705.    ldy instrValue+1
  1706.    sta number+0
  1707.    sty number+1
  1708.    lda instrValueType
  1709.    bmi +
  1710.    ldx #number
  1711.    jsr putnum
  1712.    jmp ++
  1713. +  lda #"?"
  1714.    jsr putchar
  1715. +  lda #chrCR
  1716.    jsr putchar
  1717.  
  1718.    ;** get opcode for instr/addrmode
  1719. +  nop
  1720. -  lda instrNum
  1721.    ldx instrAddrMode
  1722.    jsr instrGetOpcode
  1723.    bcc +
  1724.    ldx instrAddrMode
  1725.    lda instrAdmodePromote,x
  1726.    sta instrAddrMode
  1727.    bne -
  1728.    lda #errWrongAdmode
  1729.    jmp error
  1730. +  bit debug
  1731.    bpl ++
  1732.    lda #<instrCodeMsg
  1733.    ldy #>instrCodeMsg
  1734.    jsr puts
  1735.    lda address+1
  1736.    jsr puthex
  1737.    lda address+0
  1738.    jsr puthex
  1739.    lda #":"
  1740.    jsr putchar
  1741.    lda #" "
  1742.    jsr putchar
  1743.    lda instrOpcode
  1744.    jsr puthex
  1745.    lda instrLen
  1746.    cmp #1
  1747.    beq +
  1748.    lda #" "
  1749.    jsr putchar
  1750.    lda instrValue+0
  1751.    jsr puthex
  1752.    lda instrLen
  1753.    cmp #2
  1754.    beq +
  1755.    lda #" "
  1756.    jsr putchar
  1757.    lda instrValue+1
  1758.    jsr puthex
  1759. +  lda #chrCR
  1760.    jsr putchar
  1761.  
  1762.    ;** store the instruction into memory
  1763. +  lda instrOpcode
  1764.    sta memPutVals+0
  1765.    lda instrValue+0
  1766.    ldy instrValue+1
  1767.    sta memPutVals+1
  1768.    sty memPutVals+2
  1769.    ldx address+0
  1770.    ldy address+1
  1771.    lda instrLen
  1772.    jsr memPut
  1773.  
  1774.    ;** add relocatable reference
  1775.    lda instrValueType
  1776.    beq ++
  1777.    cmp #$04
  1778.    bcs ++
  1779.    ldx address+0
  1780.    ldy address+1
  1781.    inx
  1782.    bne +
  1783.    iny
  1784. +  jsr recordRelocRef
  1785.  
  1786.    ;** increment address and finish
  1787. +  clc
  1788.    lda address+0
  1789.    adc instrLen
  1790.    sta address+0
  1791.    bcc +
  1792.    inc address+1
  1793.    bne +
  1794.    lda #errAddressWrap
  1795.    jmp error
  1796. +  jmp parseEnd
  1797.  
  1798. instrMsg = *
  1799.    db "got processor instruction="
  1800.    db 0
  1801. instrAddrMsg1 = *
  1802.    db "got address mode="
  1803.    db 0
  1804. instrAddrMsg2 = *
  1805.    db ", value="
  1806.    db 0
  1807. instrCodeMsg = *
  1808.    db "code = "
  1809.    db 0
  1810. instrAdmodePromote = *
  1811.    db $00,$00,$00,$00,$07,$08,$09,$00,$00,$00,$00,$00,$00
  1812.  
  1813. ; num  name       gen  byt  tokens
  1814. ; ---  ---------  ---  ---  -------
  1815. ; 00.  <none>     00.    0  <none>
  1816. ; 01.  implied    00.    1  CR
  1817. ; 02.  immediate  00.    2  #     / exp8  / CR
  1818. ; 03.  relative   00.    2  exp16 / CR
  1819. ; 04.  zeropage   07.    2  exp8  / CR
  1820. ; 05.  zp,x       08.    2  exp8  / ,     / x   / CR
  1821. ; 06.  zp,y       09.    2  exp8  / ,     / y   / CR
  1822. ; 07.  absolute   00.    3  exp16 / CR
  1823. ; 08.  abs,x      00.    3  exp16 / ,     / x   / CR
  1824. ; 09.  abs,y      00.    3  exp16 / ,     / y   / CR
  1825. ; 10.  indirect   00.    3  (     / exp16 / )   / CR
  1826. ; 11.  (ind,x)    00.    2  (     / exp8  / ,   / x   / )  / CR
  1827. ; 12.  (ind),y    00.    2  (     / exp8  / )   / ,   / y  / CR
  1828. ;
  1829. ; All zp modes can be promoted to abs except for zp,y for stx and zp,x for sty.
  1830. ; Indy mode causes some special problems--I'll have to patch the hole.
  1831.  
  1832. instrGetAddrMode = *  ;( address, instrNum ) : instrAddrMode, instrValue,
  1833.    lda #$00             ;                        instrValueType
  1834.    sta instrValue+0
  1835.    sta instrValue+1
  1836.    sta instrValueType
  1837.    lda tokenNextChar
  1838.    cmp #"#"
  1839.    beq admodeImmediate
  1840.    cmp #"("
  1841.    beq admodeIndirect
  1842.    cmp #chrCR
  1843.    bne +
  1844.    jsr getToken  ;get the CR
  1845.    lda #01       ;implied
  1846.    sta instrAddrMode
  1847.    rts
  1848. +  lda instrNum
  1849.    cmp #14
  1850.    bcs +
  1851.    cmp #4
  1852.    bcc +
  1853.    cmp #7
  1854.    beq +
  1855.    cmp #11
  1856.    beq +
  1857.    jmp admodeRelative
  1858.    ;** zp or abs, straight or indexed
  1859. +  lda #0
  1860.    jsr admodeHandleExpr
  1861.    ldy #04  ;zeropage mode
  1862.    cpx #1
  1863.    beq +
  1864.    ldy #07  ;absolute mode
  1865. +  sty instrAddrMode
  1866.    cmp #chrCR
  1867.    bne +
  1868.    rts
  1869. +  cmp #","
  1870.    beq +
  1871. -  jmp syntaxError
  1872. +  jsr admodeGetXY
  1873.    inc instrAddrMode
  1874.    cpx #0
  1875.    beq +
  1876.    inc instrAddrMode
  1877. +  cmp #chrCR
  1878.    bne -
  1879.    rts
  1880.  
  1881. admodeImmediate = *
  1882.    jsr getToken  ;get the "#"
  1883.    lda #1
  1884.    jsr admodeHandleExpr
  1885.    cmp #chrCR
  1886.    beq +
  1887.    jmp syntaxError
  1888. +  lda #02
  1889.    sta instrAddrMode
  1890.    rts
  1891.  
  1892. admodeRelative = *
  1893.    lda #2
  1894.    jsr admodeHandleExpr
  1895.    cmp #chrCR
  1896.    beq +
  1897.    jmp syntaxError
  1898. +  lda #03
  1899.    sta instrAddrMode
  1900.    rts
  1901.  
  1902. admodeIndirect = *
  1903.    jsr getToken  ;get the "("
  1904.    lda #0
  1905.    jsr parseExpression
  1906.    cmp #","
  1907.    beq admodeIndX
  1908.    cmp #")"
  1909.    beq +
  1910. -  jmp syntaxError
  1911. +  jsr getToken
  1912.    ldx tokenType
  1913.    cpx #tokenSpecial
  1914.    bne -
  1915.    lda tokenChar
  1916.    cmp #","
  1917.    beq admodeIndY
  1918.    cmp #chrCR
  1919.    bne -
  1920.    lda #0
  1921.    sta admodeMustBe
  1922.    jsr admodeHandleExprIn
  1923.    lda #10
  1924.    sta instrAddrMode
  1925.    rts
  1926.  
  1927.    admodeIndX = *
  1928.    lda #1
  1929.    sta admodeMustBe
  1930.    jsr admodeHandleExprIn
  1931.    jsr admodeGetXY
  1932.    cpx #0
  1933.    beq +
  1934. -  jmp syntaxError
  1935. +  cmp #")"
  1936.    bne -
  1937.    jsr getToken
  1938.    cpx #tokenSpecial
  1939.    bne -
  1940.    cmp #chrCR
  1941.    bne -
  1942.    lda #11
  1943.    sta instrAddrMode
  1944.    rts
  1945.  
  1946.    admodeIndY = *
  1947.    lda #1
  1948.    sta admodeMustBe
  1949.    jsr admodeHandleExprIn
  1950.    jsr admodeGetXY
  1951.    cpx #1
  1952.    beq +
  1953. -  jmp syntaxError
  1954. +  cmp #chrCR
  1955.    bne -
  1956.    lda #12
  1957.    sta instrAddrMode
  1958.    rts
  1959.  
  1960. admodeGetXY = *  ;( .X=tokenType, token ) : .A=specialChar, .X=0:x/1:y
  1961.    jsr getToken
  1962.    ldx tokenType
  1963.    cpx #tokenIdentifier
  1964.    beq +
  1965. -  jmp syntaxError
  1966. +  lda stringLen
  1967.    cmp #1
  1968.    bne -
  1969.    lda stringBuf+0
  1970.    ldy #0
  1971.    cmp #"x"
  1972.    beq +
  1973.    iny
  1974.    cmp #"y"
  1975.    bne -
  1976. +  tya
  1977.    pha
  1978.    jsr getToken
  1979.    ldx tokenType
  1980.    cpx #tokenSpecial
  1981.    bne -
  1982.    pla
  1983.    tax
  1984.    lda tokenChar
  1985.    rts
  1986.  
  1987. admodeMustBe : buf 1
  1988. admodeChar   : buf 1
  1989. admodeHole   : buf 1
  1990.  
  1991. admodeHandleExpr = *  ;( .A=1:byte+2:rel, address ) : .A=nextChar, .X=valBytes,
  1992.    sta admodeMustBe   ;                               instrValue, instrValueType
  1993.    lda #0
  1994.    jsr parseExpression
  1995.    sta admodeChar
  1996.  
  1997.    admodeHandleExprIn = *
  1998.    jsr evaluateExpression
  1999.    lda idVal+0
  2000.    ldy idVal+1
  2001.    sta instrValue+0
  2002.    sty instrValue+1
  2003.    lda idType
  2004.    sta instrValueType
  2005.    bcs admodeExprHole
  2006.    lda idVal+2
  2007.    ora idVal+3
  2008.    beq +
  2009. -  lda #errValueTooLarge
  2010.    jmp error
  2011. +  lda admodeMustBe
  2012.    bne ++
  2013.    ldx #2
  2014.    lda instrValue+1
  2015.    bne +
  2016. -  ldx #1
  2017. +  lda admodeChar
  2018.    rts
  2019. +  cmp #1  ;must be byte
  2020.    bne +
  2021.    lda instrValue+1
  2022.    bne --
  2023.    beq -
  2024. +  clc     ;must be relative
  2025.    lda address+0
  2026.    adc #2
  2027.    sta work+14
  2028.    lda address+1
  2029.    adc #0
  2030.    sta work+15
  2031.    sec
  2032.    lda instrValue+0
  2033.    sbc work+14
  2034.    sta instrValue+0
  2035.    tax
  2036.    lda instrValue+1
  2037.    sbc work+15
  2038.    sta instrValue+1
  2039.    cmp #0
  2040.    bne +
  2041.    cpx #128
  2042.    bcc ++
  2043. -  lda #errBranchTooFar
  2044.    jmp error
  2045. +  cmp #$ff
  2046.    bne -
  2047.    cpx #128
  2048.    bcc -
  2049. +  lda #0
  2050.    sta instrValue+1
  2051.    ldx #1
  2052.    lda admodeChar
  2053.    rts
  2054.  
  2055.    admodeExprHole = *
  2056.    ;** get presumed hole type
  2057.    lda #$02    ;holeType=word
  2058.    ldx admodeMustBe
  2059.    beq +
  2060.    lda #$01    ;holeType=byte
  2061.    cpx #1
  2062.    beq +
  2063.    lda #$40      ;holeType=branch
  2064.    ;** check for special cases of "stx zp,y" and "sty zp,x" which must be zp
  2065. +  cmp #$02
  2066.    bne +
  2067.    ldx instrNum
  2068.    cpx #49       ;instr.49==stx
  2069.    bcc +
  2070.    cpx #50+1     ;instr.50==sty
  2071.    bcs +
  2072.    ldx admodeChar
  2073.    cpx #","
  2074.    bne +
  2075.    lda #$01      ;is one of specials, so hole must be 8-bits
  2076.    ;** record the hole
  2077. +  pha
  2078.    tax
  2079.    lda #1
  2080.    jsr addMemoryHole
  2081.    ;** get the return values
  2082.    pla
  2083.    cmp #$40
  2084.    bne +
  2085.    lda #1
  2086. +  tax
  2087.    ldy #$80
  2088.    sty instrValueType
  2089.    ldy #$00
  2090.    sty instrValue+0
  2091.    sty instrValue+1
  2092.    lda admodeChar
  2093.    rts
  2094.  
  2095. ;taken from Mighty Mon 4.0: instr# + addrMode -> opcode conversion + length
  2096.  
  2097. opcodeBase      = work+14
  2098. opcodeAdmodeNum = work+15
  2099.  
  2100. instrGetOpcode = *  ;( .A=instr#, .X=addrMode ) : instrOpcode, instrLen, .CS=inv
  2101.    tay                          ;.$da4b  [a8      ]  tay
  2102.    lda opcodeBaseTab,y          ;.$da4c  [b9 55 c2]  lda $c255,y
  2103.    sta opcodeBase               ;.$da4f  [85 48   ]  sta $48
  2104.    stx opcodeAdmodeNum          ;.$da51  [86 49   ]  stx $49
  2105.    lda opcodeAdmodeTab,y        ;.$da53  [b9 8d c2]  lda $c28d,y
  2106.    bmi ++                       ;.$da56  [30 0e   ]  bmi $da66
  2107.    cmp opcodeAdmodeNum          ;.$da58  [c5 49   ]  cmp $49
  2108.    bne +                        ;.$da5a  [d0 08   ]  bne $da64
  2109.    lda opcodeLenTab,x           ;.$da5c  [bd 6c c3]  lda $c36c,x
  2110.    tax                          ;.$da5f  [aa      ]  tax
  2111.    lda opcodeBase               ;.$da60  [a5 48   ]  lda $48
  2112.    sta instrOpcode              ;
  2113.    stx instrLen                 ;
  2114.    clc                          ;.$da62  [18      ]  clc
  2115.    rts                          ;.$da63  [60      ]  rts
  2116. +  nop                          ;
  2117. -  sec                          ;.$da64  [38      ]  sec
  2118.    rts                          ;.$da65  [60      ]  rts
  2119.                                 ;
  2120. +  and #$7f                     ;.$da66  [29 7f   ]  and #$7f
  2121.    tay                          ;.$da68  [a8      ]  tay
  2122.    lda opcodeOrOffTab,y         ;.$da69  [b9 60 c3]  lda $c360,y
  2123.    clc                          ;.$da6c  [18      ]  clc
  2124.    adc opcodeAdmodeNum          ;.$da6d  [65 49   ]  adc $49
  2125.    tay                          ;.$da6f  [a8      ]  tay
  2126.    dey                          ; <the ad modes start from 1 not 0 like in mm4>
  2127.    lda opcodeOrMaskTab,y        ;.$da70  [b9 d2 c2]  lda $c2d2,y
  2128.    bmi -                        ;.$da73  [30 ef   ]  bmi $da64
  2129.    ora opcodeBase               ;.$da75  [05 48   ]  ora $48
  2130.    tay                          ;.$da77  [a8      ]  tay
  2131.    lda opcodeLenTab,x           ;.$da78  [bd 6c c3]  lda $c36c,x
  2132.    tax                          ;.$da7b  [aa      ]  tax
  2133.    tya                          ;.$da7c  [98      ]  tya
  2134.    sta instrOpcode              ;
  2135.    stx instrLen                 ;
  2136.    clc                          ;.$da7d  [18      ]  clc
  2137.    rts                          ;.$da7e  [60      ]  rts
  2138.  
  2139. opcodeBaseTab = *
  2140.    db $00,$61,$21,$02,$90,$b0,$f0,$24,$30,$d0,$10,$00,$50,$70,$18,$d8
  2141.    db $58,$b8,$c1,$e0,$c0,$c6,$ca,$88,$41,$e6,$e8,$c8,$4c,$20,$a1,$a2
  2142.    db $a0,$42,$ea,$01,$48,$08,$68,$28,$22,$62,$40,$60,$e1,$38,$f8,$78
  2143.    db $81,$86,$84,$aa,$a8,$ba,$8a,$9a,$98
  2144.  
  2145. opcodeAdmodeTab = *
  2146.    db $00,$81,$81,$82,$03,$03,$03,$83,$03,$03,$03,$01,$03,$03,$01,$01
  2147.    db $01,$01,$81,$84,$84,$85,$01,$01,$81,$85,$01,$01,$86,$07,$81,$87
  2148.    db $88,$82,$01,$81,$01,$01,$01,$01,$82,$82,$01,$01,$81,$01,$01,$01
  2149.    db $89,$8a,$8b,$01,$01,$01,$01,$01,$01
  2150.  
  2151. opcodeLenTab = *
  2152.    db $00,$01,$02,$02,$02,$02,$02,$03,$03,$03,$03,$02,$02
  2153.  
  2154. opcodeOrOffTab = *
  2155.    db 0,0,12,24,36,48,60,72,84,96,108,120
  2156.  
  2157. opcodeOrMaskTab = *
  2158.    ;      01  02  03  04  05  06  07  08  09  10  11  12 : addrMode
  2159.    ;      --  --  --  --  --  --  --  --  --  --  --  --     <if compressed>
  2160.    db $80,$08,$80,$04,$14,$80,$0c,$1c,$18,$80,$00,$10  ;[trim:1+0=1] [add=2]
  2161.    db $08,$80,$80,$04,$14,$80,$0c,$1c,$80,$80,$80,$80  ;[trim:0+4=4] [add=2]
  2162.    db $80,$80,$80,$04,$80,$80,$0c,$80,$80,$80,$80,$80  ;[trim:3+5=8] [add=2]
  2163.    db $80,$00,$80,$04,$80,$80,$0c,$80,$80,$80,$80,$80  ;[trim:1+5=6] [add=2]
  2164.    db $80,$80,$80,$04,$14,$80,$0c,$1c,$80,$80,$80,$80  ;[trim:3+4=7] [add=2]
  2165.    db $80,$80,$80,$80,$80,$80,$00,$80,$80,$20,$80,$80  ;[trim:6+2=8] [add=2]
  2166.    db $80,$00,$80,$04,$80,$14,$0c,$80,$1c,$80,$80,$80  ;[trim:1+3=4] [add=2]
  2167.    db $80,$00,$80,$04,$14,$80,$0c,$1c,$80,$80,$80,$80  ;[trim:1+4=5] [add=2]
  2168.    db $80,$80,$80,$04,$14,$80,$0c,$1c,$18,$80,$00,$10  ;[trim:3+0=3] [add=2]
  2169.    db $80,$80,$80,$04,$80,$14,$0c,$80,$80,$80,$80,$80  ;[trim:3+5=8] [add=2]
  2170.    db $80,$80,$80,$04,$14,$80,$0c,$80,$80,$80,$80,$80  ;[trim:3+5=8] [add=2]
  2171.  
  2172. ;======== expression handling ========
  2173.  
  2174. parseExprType : buf 1
  2175.  
  2176. parseExpression = *  ;( .A=type(0=num,1=either) ) : .A=nextSpecialChar,.X=type
  2177.    sta parseExprType
  2178.    ldx #16
  2179.    stx expOffset
  2180.    lda #"+"
  2181.    sta expOp+0,x
  2182.    ldx #3
  2183. -  lda #0
  2184.    sta expHoleType,x
  2185.    lda #aceMemNull
  2186.    sta expHoleAddr,x
  2187.    lda sourceLine,x
  2188.    sta expSrcLine,x
  2189.    lda filePtr,x
  2190.    sta expSrcFile,x
  2191.    dex
  2192.    bpl -
  2193.    lda sourceCol
  2194.    sta expSrcCol
  2195.    bit debug
  2196.    bpl expGetOperand
  2197.    lda #<parseExprMsg
  2198.    ldy #>parseExprMsg
  2199.    jsr puts
  2200.  
  2201.    ;** expecting operand
  2202.    expGetOperand = *
  2203.    lda #0
  2204.    sta expPlusCount
  2205.    sta expMinusCount
  2206.    sta expLessCount
  2207.    sta expGreaterCount
  2208.    expGetOperandCont = *
  2209.    ldx expOffset
  2210.    lda #0
  2211.    sta expReserved,x
  2212.    jsr getToken
  2213.    cpx #tokenSpecial
  2214.    bne expNotSpecial
  2215.    lda tokenChar
  2216.    cmp #"+"
  2217.    bne +
  2218.    inc expPlusCount
  2219.    jmp expGetOperandCont
  2220. +  cmp #"-"
  2221.    bne +
  2222.    inc expMinusCount
  2223.    jmp expGetOperandCont
  2224. +  cmp #">"
  2225.    bne +
  2226.    inc expGreaterCount
  2227.    jmp expGetOperandCont
  2228. +  cmp #"<"
  2229.    bne +
  2230.    inc expLessCount
  2231.    jmp expGetOperandCont
  2232. +  cmp #"*"
  2233.    bne +
  2234.    jmp expOpnStar
  2235. +  jmp expOpnRelative
  2236.  
  2237.    expNotSpecial = *
  2238.    ldx expOffset
  2239.    lda expMinusCount
  2240.    and #$01
  2241.    lsr
  2242.    ror
  2243.    sta expSign,x
  2244.    jsr expFigureHiLo
  2245.    sta expHiLo,x
  2246.    lda #$00
  2247.    sta expType,x
  2248.    ldx tokenType
  2249.    cpx #tokenIdentifier
  2250.    bne +
  2251.    lda #0
  2252.    jmp expOpnIdentifier
  2253. +  cpx #tokenNumber
  2254.    bne +
  2255.    jmp expOpnNumber
  2256. +  cpx #tokenString
  2257.    bne +
  2258.    jmp expOpnString
  2259. +  jmp syntaxError
  2260.    parseExprMsg = *
  2261.    db "...must parse an expression..."
  2262.    db chrCR,0
  2263.  
  2264. ;"Asteroids do not concern me, Admiral.  I want that ship, not excuses!"
  2265. ;"Mudhole!?  Slimy!!?  My home, this is!"
  2266.  
  2267. expFigureHiLoWork : buf 1
  2268.  
  2269. expFigureHiLo = * ; ( ) : .A=HiLo_value ;.X:unchanged
  2270.    lda expGreaterCount
  2271.    cmp #16
  2272.    bcc +
  2273.    lda #15
  2274. +  asl
  2275.    asl
  2276.    asl
  2277.    asl
  2278.    sta expFigureHiLoWork
  2279.    lda expLessCount
  2280.    cmp #2
  2281.    bcc +
  2282.    lda #1
  2283. +  ora expFigureHiLoWork
  2284.    rts
  2285.  
  2286. expOpnRelExit : buf 1  ;whether to exit exp after relative ref.
  2287.  
  2288. expOpnRelative = *
  2289.    ldx #0
  2290.    cmp #":"
  2291.    beq +
  2292.    ldx #$ff
  2293. +  stx expOpnRelExit
  2294.    lda expPlusCount  ;there must be some pluses or minuses
  2295.    ora expMinusCount
  2296.    bne +
  2297.    jmp syntaxError
  2298. +  jsr expFigureHiLo
  2299.    ldx expOffset
  2300.    sta expHiLo,x
  2301.    lda #0
  2302.    sta expSign,x
  2303.    lda #"+"
  2304.    ldy expPlusCount
  2305.    beq +
  2306.    ldx expMinusCount
  2307.    beq ++
  2308.    jmp syntaxError
  2309. +  lda #"-"
  2310.    ldy expMinusCount
  2311.    bne +
  2312.    jmp syntaxError
  2313. +  dey
  2314.    jsr genRelLabel
  2315.    lda expOpnRelExit
  2316.    ;** fall through
  2317.  
  2318. expOpnIdentifier = *
  2319.    pha
  2320.    jsr findSymbol
  2321.    ldx expOffset
  2322.    lda idType
  2323.    cmp #$81
  2324.    bcc +
  2325.    cmp #$ff
  2326.    beq +
  2327.    lda #errNonNumIdExpr
  2328.    jmp error
  2329. +  sta expType,x
  2330.    ldy #0
  2331.    cmp #$80
  2332.    bcs +
  2333. -  lda idVal,y
  2334.    sta expValue,x
  2335.    inx
  2336.    iny
  2337.    cpy #4
  2338.    bcc -
  2339.    pla
  2340.    jmp expGetOperator
  2341. +  inc expUnresCnt
  2342. -  lda idPtr,y
  2343.    sta expValue,x
  2344.    inx
  2345.    iny
  2346.    cpy #4
  2347.    bcc -
  2348.    pla
  2349.    jmp expGetOperator
  2350.  
  2351. expOpnStar = *
  2352.    bit originSet
  2353.    bmi +
  2354.    lda #errOriginNotSet
  2355.    jmp error
  2356. +  ldx expOffset
  2357.    lda expMinusCount
  2358.    and #$01
  2359.    lsr
  2360.    ror
  2361.    sta expSign,x
  2362.    jsr expFigureHiLo
  2363.    sta expHiLo,x
  2364.    lda #$01
  2365.    sta expType,x
  2366.    lda address+0
  2367.    sta expValue+0,x
  2368.    lda address+1
  2369.    sta expValue+1,x
  2370.    lda #0
  2371.    sta expValue+2,x
  2372.    sta expValue+3,x
  2373.    lda #0
  2374.    jmp expGetOperator
  2375.  
  2376. expOpnNumber = *
  2377.    ldx expOffset
  2378.    lda #$00
  2379.    sta expType,x
  2380.    ldy #0
  2381. -  lda number,y
  2382.    sta expValue,x
  2383.    inx
  2384.    iny
  2385.    cpy #4
  2386.    bcc -
  2387.    lda #0
  2388.    jmp expGetOperator
  2389.  
  2390. expOpnString = *
  2391.    lda stringLen
  2392.    cmp #1
  2393.    bne +
  2394.    ;** interpret string as number
  2395.    ldx expOffset
  2396.    lda #$00
  2397.    sta expType,x
  2398.    lda stringBuf+0
  2399.    sta expValue+0,x
  2400.    lda #0
  2401.    sta expValue+1,x
  2402.    sta expValue+2,x
  2403.    sta expValue+3,x
  2404.    lda #0
  2405.    jmp expGetOperator
  2406.  
  2407.    ;** interpret string as actual string
  2408. +  lda expPlusCount
  2409.    ora expMinusCount
  2410.    ora expLessCount
  2411.    ora expGreaterCount
  2412.    beq +
  2413. -  lda #errInvalStrOpers
  2414.    jmp error
  2415. +  lda expOffset
  2416.    cmp #16
  2417.    bne -
  2418.    lda parseExprType
  2419.    bne +
  2420. -  jmp syntaxError
  2421. +  jsr getToken
  2422.    cpx #tokenSpecial
  2423.    bne -
  2424. +  ldx #$80
  2425.    rts
  2426.  
  2427. expGetOperator = *  ;(.A=exitFlag)
  2428.    pha
  2429.    clc
  2430.    lda expOffset
  2431.    adc #14
  2432.    sta expOffset
  2433.    bcc +
  2434.    lda #errTooManyOperands
  2435.    jmp error
  2436. +  pla
  2437.    cmp #0
  2438.    beq +
  2439. -  ldx expOffset
  2440.    txa
  2441.    sta expLength
  2442.    lda sourceCol
  2443.    sta expSrcCol
  2444.    lda tokenChar
  2445.    ldx #0
  2446.    rts
  2447. +  jsr getToken
  2448.    ldx tokenType
  2449.    cpx #tokenSpecial
  2450.    beq +
  2451.    jmp syntaxError
  2452. +  lda tokenChar
  2453.    cmp #"+"
  2454.    beq +
  2455.    cmp #"-"
  2456.    bne -
  2457. +  ldx expOffset
  2458.    sta expOp,x
  2459.    jmp expGetOperand
  2460.  
  2461. evaluateExpression = *  ;( expTable ) : .CS=unresolved, idVal, idType
  2462.    ldx #3
  2463.    lda #0
  2464. -  sta idVal,x
  2465.    dex
  2466.    bpl -
  2467.    sta idType
  2468.    lda expUnresCnt
  2469.    beq +
  2470.    lda #$80
  2471.    sta idType
  2472.    sec
  2473.    rts
  2474.  + ldx #16
  2475.    stx expOffset
  2476.  
  2477.    evalNext = *
  2478.    ldx expOffset
  2479.    lda expType,x
  2480.    eor idType    ;(+-:val+val=val,adr+val=adr,val+adr=adr,adr+adr=val)
  2481.    sta idType
  2482.    ldy #$00
  2483. -  lda expValue,x
  2484.    sta number,y
  2485.    inx
  2486.    iny
  2487.    cpy #4
  2488.    bcc -
  2489.    ldx expOffset
  2490.    lda expSign,x
  2491.    bpl +
  2492.    jsr evalNegate
  2493. +  ldx expOffset
  2494.    cpx #16
  2495.    beq +
  2496.    lda expHiLo,x
  2497.    beq +
  2498.    jsr evalHiLo
  2499. +  ldx expOffset
  2500.    lda expOp,x
  2501.    cmp #"+"
  2502.    beq +
  2503.    jsr evalNegate
  2504.    ;** perform addition
  2505. +  clc
  2506.    ldy #4
  2507.    ldx #0
  2508. -  lda idVal,x
  2509.    adc number,x
  2510.    sta idVal,x
  2511.    inx
  2512.    dey
  2513.    bne -
  2514.    ;** go onto next operation
  2515.    clc
  2516.    lda expOffset
  2517.    adc #14
  2518.    sta expOffset
  2519.    cmp expLength
  2520.    bcc evalNext
  2521.    ;** check global hi-lo
  2522.    lda expHiLo+16
  2523.    beq +
  2524.    ldx #3
  2525. -  lda idVal,x
  2526.    sta number,x
  2527.    dex
  2528.    bpl -
  2529.    lda expHiLo+16
  2530.    jsr evalHiLo
  2531.    ldx #3
  2532. -  lda number,x
  2533.    sta idVal,x
  2534.    dex
  2535.    bpl -
  2536. +  clc
  2537.    bit debug
  2538.    bmi +
  2539.    rts
  2540. +  lda #<evalMsg
  2541.    ldy #>evalMsg
  2542.    jsr puts
  2543.    ldx #idVal
  2544.    jsr putnum
  2545.    lda #","
  2546.    jsr putchar
  2547.    lda #" "
  2548.    jsr putchar
  2549.    lda #"v"
  2550.    ldx idType
  2551.    beq +
  2552.    lda #"a"
  2553. +  jsr putchar
  2554.    lda #chrCR
  2555.    jsr putchar
  2556.    clc
  2557.    rts
  2558.    evalMsg = *
  2559.    db "evaluate: result="
  2560.    db 0
  2561.  
  2562. evalNegate = *  ;( number ) : -number
  2563.    sec
  2564.    ldy #4
  2565.    ldx #0
  2566. -  lda #0
  2567.    sbc number,x
  2568.    sta number,x
  2569.    inx
  2570.    dey
  2571.    bne -
  2572.    rts
  2573.  
  2574. evalHiLoCnt : buf 1
  2575.  
  2576. evalHiLo = *
  2577.    ;value $10 will extract high byte of addr, $01 will extract low byte
  2578.    pha
  2579.    lsr
  2580.    lsr
  2581.    lsr
  2582.    lsr
  2583.    tax
  2584.    beq +
  2585. -  lda number+1
  2586.    sta number+0
  2587.    lda number+2
  2588.    sta number+1
  2589.    lda number+3
  2590.    sta number+2
  2591.    lda #$00
  2592.    sta number+3
  2593.    dex
  2594.    bne -
  2595. +  pla
  2596.    and #$0f
  2597.    beq +
  2598.    ldx #0
  2599.    stx number+3
  2600.    stx number+2
  2601.    stx number+1
  2602. +  rts
  2603.  
  2604. ;======== symbol table management ========
  2605.  
  2606. findSymbol = *  ;( stringBuf, stringLen ) : .A=code,idPtr,idVal
  2607.    ;** ret: code .A=(symFound,symUnresolved,symNew)
  2608.    jsr hash
  2609.    ldy #3
  2610. -  lda (hashPtr),y
  2611.    sta mp,y
  2612.    dey
  2613.    bpl -
  2614.    findSymNext = *
  2615.    lda mp+3
  2616.    cmp #aceMemNull
  2617.    bne +
  2618.    jmp findSymCreate
  2619. +  lda #<symBuf
  2620.    ldy #>symBuf
  2621.    sta zp+0
  2622.    sty zp+1
  2623.    lda #12+8+1
  2624.    ldy #0
  2625.    jsr fetch
  2626.    lda symNameLen
  2627.    cmp stringLen
  2628.    bne findSymCont
  2629.    cmp #8+1
  2630.    bcc +
  2631.    clc
  2632.    adc #12+1
  2633.    ldy #0
  2634.    jsr fetch
  2635. +  ldx #0
  2636. -  lda stringBuf,x
  2637.    beq +
  2638.    cmp symName,x
  2639.    bne findSymCont
  2640.    inx
  2641.    bne -
  2642. +  ldx #3
  2643. -  lda mp,x
  2644.    sta idPtr,x
  2645.    lda symValue,x
  2646.    sta idVal,x
  2647.    dex
  2648.    bpl -
  2649.    lda symType
  2650.    sta idType
  2651.    lda #symFound
  2652.    bit symType
  2653.    bpl +
  2654.    lda #symUnresolved
  2655. +  rts
  2656.  
  2657.    findSymCont = *
  2658.    ldx #3
  2659. -  lda symNext,x
  2660.    sta mp,x
  2661.    dex
  2662.    bpl -
  2663.    jmp findSymNext
  2664.  
  2665. findSymCreate = *
  2666.    lda #$80
  2667.    sta symType
  2668.    sta idType
  2669.    lda #$00
  2670.    sta symClass
  2671.    sta symUnresOpnd
  2672.    lda stringLen
  2673.    sta symNameLen
  2674.    ldx #0
  2675. -  lda stringBuf,x
  2676.    sta symName,x
  2677.    beq +
  2678.    inx
  2679.    bne -
  2680. +  clc
  2681.    lda #12+1
  2682.    adc symNameLen
  2683.    ldy #0
  2684.    jsr malloc
  2685.    bcc +
  2686.    lda #errInsufficientMemory
  2687.    jmp error
  2688. +  ldy #3
  2689. -  lda #aceMemNull
  2690.    sta symValue,y
  2691.    lda #0
  2692.    sta idVal,y
  2693.    lda (hashPtr),y
  2694.    sta symNext,y
  2695.    lda mp,y
  2696.    sta idPtr,y
  2697.    sta (hashPtr),y
  2698.    dey
  2699.    bpl -
  2700.    jsr stashSymbol
  2701.    lda #symNew
  2702.    rts
  2703.  
  2704. fetchSymbol = *  ;( [mp] ) : symBuf
  2705.    lda #<symBuf
  2706.    ldy #>symBuf
  2707.    sta zp+0
  2708.    sty zp+1
  2709.    lda #12+8+1
  2710.    ldy #0
  2711.    jsr fetch
  2712.    lda symNameLen
  2713.    cmp #8+1
  2714.    bcc +
  2715.    clc
  2716.    adc #12+1
  2717.    ldy #0
  2718.    jsr fetch
  2719. +  rts
  2720.  
  2721. fetchSymbolHeader = *  ;( [mp] ) : symBuf (header)
  2722.    lda #<symBuf
  2723.    ldy #>symBuf
  2724.    sta zp+0
  2725.    sty zp+1
  2726.    lda #12
  2727.    ldy #0
  2728.    jsr fetch
  2729.    rts
  2730.  
  2731. stashSymbol = *  ;( symBuf, [mp] )
  2732.    lda #<symBuf
  2733.    ldy #>symBuf
  2734.    sta zp+0
  2735.    sty zp+1
  2736.    clc
  2737.    lda #12+1
  2738.    adc symNameLen
  2739.    ldy #0
  2740.    jsr stash
  2741.    rts
  2742.  
  2743. stashSymbolHeader = *  ;( symBuf(header), [mp] )
  2744.    lda #<symBuf
  2745.    ldy #>symBuf
  2746.    sta zp+0
  2747.    sty zp+1
  2748.    lda #12
  2749.    ldy #0
  2750.    jsr stash
  2751.    rts
  2752.  
  2753. initSymbolTable = *
  2754.    lda #<identHashTable
  2755.    ldy #>identHashTable
  2756.    ldx #hashTablePages
  2757.    ;** fall through
  2758.  
  2759. fillNull = *
  2760.    sta work+0
  2761.    sty work+1
  2762.    ldy #0
  2763.    lda #aceMemNull
  2764. -  sta (work),y
  2765.    iny
  2766.    bne -
  2767.    inc work+1
  2768.    dex
  2769.    bne -
  2770.    rts
  2771.  
  2772. findUnresSymbol = *
  2773.    ;** fetches symbol and reference
  2774.    lda #$80
  2775.    sta dumpSymOpt
  2776.    jmp dumpSymbolTableIn
  2777.    foundUnresSymbol = *
  2778.    ldx #3
  2779. -  lda symValue,x
  2780.    sta expPtr,x
  2781.    dex
  2782.    bpl -
  2783.    jsr fetchExp
  2784.    rts
  2785.  
  2786. dumpSymEntries : buf 2
  2787. dumpSymOpt : buf 1
  2788. dumpCount = idVal
  2789.  
  2790. dumpSymbolTable = *
  2791.    lda #$00
  2792.    sta dumpSymOpt
  2793.    ldx #3
  2794. -  sta dumpCount,x
  2795.    dex
  2796.    bpl -
  2797.    bit symDump
  2798.    bmi +
  2799.    rts
  2800. +  lda #<dumpSymMsg1
  2801.    ldy #>dumpSymMsg1
  2802.    jsr puts
  2803.   dumpSymbolTableIn  = *
  2804.    lda #<identHashTable
  2805.    ldy #>identHashTable
  2806.    sta hashPtr+0
  2807.    sty hashPtr+1
  2808.    lda #0
  2809.    ldy #hashTableEntriesHigh
  2810.    sta dumpSymEntries+0
  2811.    sty dumpSymEntries+1
  2812. -  jsr dumpSymBucket
  2813.    clc
  2814.    lda hashPtr+0
  2815.    adc #4
  2816.    sta hashPtr+0
  2817.    bcc +
  2818.    inc hashPtr+1
  2819. +  inc dumpSymEntries+0
  2820.    bne -
  2821.    dec dumpSymEntries+1
  2822.    bne -
  2823.    lda #<dumpSymMsg2
  2824.    ldy #>dumpSymMsg2
  2825.    jsr puts
  2826.    ldx #dumpCount
  2827.    jsr putnum
  2828.    lda #chrCR
  2829.    jsr putchar
  2830.    rts
  2831.  
  2832.    dumpSymBucket = *
  2833.    ldy #3
  2834. -  lda (hashPtr),y
  2835.    sta mp,y
  2836.    dey
  2837.    bpl -
  2838. -  lda mp+3
  2839.    cmp #aceMemNull
  2840.    bne +
  2841.    rts
  2842. +  jsr fetchSymbol
  2843.    jsr dumpSymbol
  2844.    ldx #3
  2845. -  lda symNext,x
  2846.    sta mp,x
  2847.    dex
  2848.    bpl -
  2849.    jmp --
  2850.  
  2851.    dumpSymbol = *
  2852.    bit dumpSymOpt
  2853.    bpl ++
  2854.    lda symType
  2855.    cmp #$80
  2856.    beq +
  2857.    cmp #$ff
  2858.    bne ++
  2859. +  pla ;** pop call from dumpSymBucket
  2860.    pla
  2861.    pla ;** pop call from dumpSymbolTable
  2862.    pla
  2863.    jmp foundUnresSymbol
  2864. +  ldx #dumpCount
  2865.    jsr incLong
  2866.    lda #0
  2867.    sta number+2
  2868.    sta number+3
  2869.    sec
  2870.    lda hashPtr+0
  2871.    sbc #<identHashTable
  2872.    sta number+0
  2873.    lda hashPtr+1
  2874.    sbc #>identHashTable
  2875.    sta number+1
  2876.    lsr number+1
  2877.    ror number+0
  2878.    lsr number+1
  2879.    ror number+0
  2880.    ldx #number
  2881.    ldy #4
  2882.    jsr wputnum
  2883.    lda #2
  2884.    jsr space
  2885.    ldx #3
  2886. -  lda symValue,x
  2887.    sta number,x
  2888.    dex
  2889.    bpl -
  2890.    lda number+3
  2891.    jsr puthex
  2892.    lda number+2
  2893.    jsr puthex
  2894.    lda number+1
  2895.    jsr puthex
  2896.    lda number+0
  2897.    jsr puthex
  2898.    lda #1
  2899.    jsr space
  2900.    ldx #number
  2901.    ldy #10
  2902.    jsr wputnum
  2903.    lda #2
  2904.    jsr space
  2905.    lda #"v"
  2906.    ldx symType
  2907.    beq +
  2908.    lda #"a"
  2909.    bit symType
  2910.    bpl +
  2911.    lda #"?"
  2912. +  jsr putchar
  2913.    lda #2
  2914.    jsr space
  2915.    lda #<symName
  2916.    ldy #>symName
  2917.    jsr puts
  2918.    lda #chrCR
  2919.    jsr putchar
  2920.    jsr checkStop
  2921.    rts
  2922.  
  2923.    spaceCount : buf 1
  2924.  
  2925.    space = *
  2926.    sta spaceCount
  2927. -  lda #" "
  2928.    jsr putchar
  2929.    dec spaceCount
  2930.    bne -
  2931.    rts
  2932.  
  2933.    dumpSymMsg1 = *
  2934.    db "HASH  HEXVALUE    DECIMAL  T  NAME"
  2935.    db chrCR
  2936.    db "----  -------- ----------  -  -----"
  2937.    db chrCR,0
  2938.    dumpSymMsg2 = *
  2939.    db "--"
  2940.    db chrCR
  2941.    db "Number of symbols: "
  2942.    db 0
  2943. ;1234567890123456789012345678901234567890
  2944.  
  2945. hashWork : buf 2
  2946.  
  2947. hash = *
  2948.    lda #$aa
  2949.    sta hashVal+0
  2950.    sta hashVal+1
  2951.    ldx #0
  2952. -  lda stringBuf,x
  2953.    bne +
  2954.    lda hashVal+0
  2955.    sta hashPtr+0
  2956.    lda hashVal+1
  2957.    and #hashTableMask
  2958.    asl hashPtr+0
  2959.    rol
  2960.    asl hashPtr+0
  2961.    rol
  2962.    sta hashPtr+1
  2963.    clc
  2964.    lda hashPtr+0
  2965.    adc #<identHashTable
  2966.    sta hashPtr+0
  2967.    lda hashPtr+1
  2968.    adc #>identHashTable
  2969.    sta hashPtr+1
  2970.    rts
  2971.    ;** hashVal := hashVal * 37;
  2972. +  lda hashVal+0
  2973.    ldy hashVal+1
  2974.    sta hashWork+0
  2975.    sty hashWork+1
  2976.    asl              ;times 2
  2977.    rol hashVal+1
  2978.    asl              ;times 4
  2979.    rol hashVal+1
  2980.    asl              ;times 8
  2981.    rol hashVal+1
  2982.    jsr hashAddWork  ;times 9
  2983.    asl              ;times 18
  2984.    rol hashVal+1
  2985.    asl              ;times 36
  2986.    rol hashVal+1
  2987.    jsr hashAddWork  ;times 37
  2988.    adc stringBuf,x
  2989.    sta hashVal+0
  2990.    bcc +
  2991.    inc hashVal+1
  2992. +  inx
  2993.    bne -
  2994.  
  2995. hashAddWork = *
  2996.    clc
  2997.    adc hashWork+0
  2998.    sta hashVal+0
  2999.    lda hashVal+1
  3000.    adc hashWork+1
  3001.    sta hashVal+1
  3002.    lda hashVal+0
  3003.    rts
  3004.  
  3005. ;======== symbols, expressions, and holes: symbol definition support ========
  3006.  
  3007. parseDefineVar = *
  3008.    jsr findSymbol
  3009.    cmp #symNew
  3010.    beq +
  3011.    lda symType
  3012.    cmp #$80
  3013.    beq +
  3014.    lda #errRedefinedSymbol
  3015.    jmp error
  3016. +  lda #$ff
  3017.    sta symType
  3018.    jsr stashSymbol
  3019.    ldx #3
  3020. -  lda idPtr,x
  3021.    sta varPtr,x
  3022.    dex
  3023.    bpl -
  3024.    rts
  3025.  
  3026. addMemoryHole = *  ;( .X=holeType, address+.A )
  3027.    ;** put in hole information
  3028.    stx expHoleType
  3029.    clc
  3030.    adc address+0
  3031.    sta expHoleAddr+0
  3032.    lda address+1
  3033.    adc #0
  3034.    sta expHoleAddr+1
  3035.    lda #0
  3036.    sta expHoleAddr+2
  3037.    sta expHoleAddr+3
  3038.    jmp addHoleIn
  3039.  
  3040. addVariableHole = *  ;( varPtr, expTable ) : ...
  3041.    ;** put in hole information
  3042.    lda #$80
  3043.    sta expHoleType
  3044.    ldx #3
  3045. -  lda varPtr,x
  3046.    sta expHoleAddr,x
  3047.    dex
  3048.    bpl -
  3049.  
  3050.    addHoleIn = *
  3051.    ;** keep a count of the global number of unresolved references
  3052.    ldx #holeCount
  3053.    jsr incLong
  3054.    ;** keep a separate count of the unresolved relative labels:they must be resd
  3055.    lda stringLen
  3056.    cmp #2
  3057.    bcc +
  3058.    lda stringBuf+1
  3059.    cmp #"+"
  3060.    beq +
  3061.    cmp #"-"
  3062.    bne ++
  3063. +  ldx #relHoleCount
  3064.    jsr incLong
  3065.    ;** allocate storage for expression descriptor
  3066. +  lda expLength
  3067.    ldy #0
  3068.    jsr malloc
  3069.    bcc +
  3070.    lda #errInsufficientMemory
  3071.    jmp error
  3072. +  ldx #3
  3073. -  lda mp,x
  3074.    sta expPtr,x
  3075.    dex
  3076.    bpl -
  3077.    ;** scan for pointers to unresolved labels, refs into corresp.reference lists
  3078.    ldx #16
  3079.    stx expOffset
  3080.  
  3081.    addHoleNext = *
  3082.    ldx expOffset
  3083.    lda expType,x
  3084.    bpl addHoleCont
  3085.    ldy #0
  3086. -  lda expValue,x
  3087.    sta mp,y
  3088.    inx
  3089.    iny
  3090.    cpy #4
  3091.    bcc -
  3092.    jsr fetchSymbolHeader
  3093.    ldx expOffset
  3094.    ldy #0
  3095. -  lda symValue,y
  3096.    sta expNextUnres,x
  3097.    lda expPtr,y
  3098.    sta symValue,y
  3099.    inx
  3100.    iny
  3101.    cpy #4
  3102.    bcc -
  3103.    ldx expOffset
  3104.    lda symUnresOpnd
  3105.    sta expNextOpnd,x
  3106.    stx symUnresOpnd
  3107.    jsr stashSymbolHeader
  3108.  
  3109.    addHoleCont = *
  3110.    clc
  3111.    lda expOffset
  3112.    adc #14
  3113.    sta expOffset
  3114.    cmp expLength
  3115.    bcc addHoleNext
  3116.  
  3117.    ;** store expression descriptor
  3118.    jmp stashExp
  3119.  
  3120. plugStackHead : buf 4
  3121. plugRecBuf    = *
  3122. plugRecNext   : buf 4
  3123. plugRecVarPtr : buf 4
  3124. plugRecIdVal  : buf 4
  3125. plugRecIdType : buf 1
  3126.  
  3127. plugStackInit = *
  3128.    lda #aceMemNull
  3129.    sta plugStackHead+3
  3130.    rts
  3131.  
  3132. plugStackPush = *  ;( varPtr, idVal, idType )
  3133.    lda #13
  3134.    ldy #0
  3135.    jsr malloc
  3136.    bcc +
  3137.    lda #errInsufficientMemory
  3138.    jsr error
  3139. +  ldx #3
  3140. -  lda plugStackHead,x
  3141.    sta plugRecNext,x
  3142.    lda mp,x
  3143.    sta plugStackHead,x
  3144.    lda varPtr,x
  3145.    sta plugRecVarPtr,x
  3146.    lda idVal,x
  3147.    sta plugRecIdVal,x
  3148.    dex
  3149.    bpl -
  3150.    lda idType
  3151.    sta plugRecIdType
  3152.    lda #<plugRecBuf
  3153.    ldy #>plugRecBuf
  3154.    sta zp+0
  3155.    sty zp+1
  3156.    lda #13
  3157.    ldy #0
  3158.    jsr stash
  3159.    rts
  3160.  
  3161. plugStackPop = *  ;( ) : varPtr, idVal, idType, .CS=empty
  3162.    ldx #3
  3163. -  lda plugStackHead,x
  3164.    sta mp,x
  3165.    dex
  3166.    bpl -
  3167.    lda mp+3
  3168.    cmp #aceMemNull
  3169.    bne +
  3170.    sec
  3171.    rts
  3172. +  lda #<plugRecBuf
  3173.    ldy #>plugRecBuf
  3174.    sta zp+0
  3175.    sty zp+1
  3176.    lda #13
  3177.    ldy #0
  3178.    jsr fetch
  3179.    lda #13
  3180.    ldy #0
  3181.    jsr free
  3182.    ldx #3
  3183. -  lda plugRecNext,x
  3184.    sta plugStackHead,x
  3185.    lda plugRecVarPtr,x
  3186.    sta varPtr,x
  3187.    lda plugRecIdVal,x
  3188.    sta idVal,x
  3189.    dex
  3190.    bpl -
  3191.    lda plugRecIdType
  3192.    sta idType
  3193.    rts
  3194.  
  3195. assignVarSave : buf 10
  3196.  
  3197. assignVariable = *  ;( varPtr, idVal, idType ) : ... ;changes idPtr,varPtr,etc.
  3198.    jsr plugStackInit
  3199.    ;** assign value to variable
  3200.    assignVarBody = *
  3201.    ldx #3
  3202. -  lda varPtr,x
  3203.    sta mp,x
  3204.    dex
  3205.    bpl -
  3206.    jsr fetchSymbolHeader
  3207.    lda symType
  3208.    cmp #$ff
  3209.    beq +
  3210.    lda #errInternAssign
  3211.    jmp error
  3212. +  ldx #3
  3213. -  lda symValue,x
  3214.    sta expPtr,x
  3215.    lda idVal,x
  3216.    sta symValue,x
  3217.    dex
  3218.    bpl -
  3219.    lda symUnresOpnd
  3220.    sta expOffset
  3221.    lda idType
  3222.    sta symType
  3223.    jsr stashSymbolHeader
  3224.  
  3225.    ;** cascade changes if necessary
  3226.    ;Run through reference list, filling in value of id, unlinking from this id.
  3227.    ;If we resolve an expression, evaluate it, and if the hole is in memory, fill
  3228.    ;it.  If the filled hole is another variable, push the <varPtr,idVal,idType>
  3229.    ;values onto the plug stack and continue with reference list for the current
  3230.    ;variable.  When we are done with the current label, pop a variable off the
  3231.    ;plug stack and continue with it.  Otherwise, exit.
  3232.    assignVarCascade = *
  3233.    lda expPtr+3
  3234.    cmp #aceMemNull
  3235.    bne +
  3236.    jsr plugStackPop
  3237.    bcc assignVarBody
  3238.    rts
  3239.    ;** fetch unresolved expression
  3240. +  jsr fetchExp
  3241.    ;** fill in value
  3242.    ldx expOffset
  3243.    lda idType
  3244.    sta expType,x
  3245.    ldy #0
  3246. -  lda idVal,y
  3247.    sta expValue,x
  3248.    inx
  3249.    iny
  3250.    cpy #4
  3251.    bcc -
  3252.    dec expUnresCnt
  3253.    bne assignVarUnresolved
  3254.    jmp assignVarResolved
  3255.  
  3256.    ;** still unresolved--stash modified expression
  3257.    assignVarUnresolved = *
  3258.    jsr stashExp
  3259.    jmp assignVarCascadeCont
  3260.  
  3261.    ;** resolved--evaluate expression, fill in hole
  3262.    assignVarResolved = *
  3263.    ldx #3
  3264. -  lda expPtr,x
  3265.    sta mp,x
  3266.    dex
  3267.    bpl -
  3268.    lda expLength
  3269.    ldy #0
  3270.    jsr free
  3271.    ;** save varPtr,idVal,idType,expOffset
  3272.    ldx #3
  3273. -  lda varPtr,x
  3274.    sta assignVarSave+0,x
  3275.    lda expHoleAddr,x
  3276.    sta varPtr,x
  3277.    lda idVal,x
  3278.    sta assignVarSave+4,x
  3279.    dex
  3280.    bpl -
  3281.    lda idType
  3282.    sta assignVarSave+8
  3283.    lda expOffset
  3284.    sta assignVarSave+9
  3285.    ldx #holeCount
  3286.    jsr decLong
  3287.    lda symClass
  3288.    cmp #$01
  3289.    beq +
  3290.    ldx #relHoleCount
  3291.    jsr decLong
  3292.    ;** evaluate new expression
  3293. +  jsr evaluateExpression
  3294.    ;** fill hole--id hole: push hole plug--do something else for memory hole
  3295.    lda expHoleType
  3296.    cmp #$80
  3297.    beq +
  3298.    jsr fillMemoryHole
  3299.    jmp ++
  3300. +  jsr plugStackPush
  3301.    ;** restore varPtr,idVal,idType,expOffset
  3302. +  ldx #3
  3303. -  lda assignVarSave+0,x
  3304.    sta varPtr,x
  3305.    lda assignVarSave+4,x
  3306.    sta idVal,x
  3307.    dex
  3308.    bpl -
  3309.    lda assignVarSave+8
  3310.    sta idType
  3311.    lda assignVarSave+9
  3312.    sta expOffset
  3313.  
  3314.    ;** go onto next unresolved expression
  3315.    assignVarCascadeCont = *
  3316.    ldx expOffset
  3317.    lda expNextOpnd,x
  3318.    sta expOffset
  3319.    ldy #0
  3320. -  lda expNextUnres,x
  3321.    sta expPtr,y
  3322.    inx
  3323.    iny
  3324.    cpy #4
  3325.    bcc -
  3326.    jmp assignVarCascade
  3327.  
  3328. fetchExp = *  ;( [expPtr] ) : expTable, mp=expPtr
  3329.    ldx #3
  3330. -  lda expPtr,x
  3331.    sta mp,x
  3332.    dex
  3333.    bpl -
  3334.    lda #<expTable
  3335.    ldy #>expTable
  3336.    sta zp+0
  3337.    sty zp+1
  3338.    lda #16+14
  3339.    ldy #0
  3340.    jsr fetch
  3341.    lda expLength
  3342.    cmp #16+14+1
  3343.    bcc +
  3344.    lda expLength
  3345.    ldy #0
  3346.    jsr fetch
  3347. +  rts
  3348.  
  3349. stashExp = *  ;( [expPtr], expTable ) : mp=expPtr
  3350.    ldx #3
  3351. -  lda expPtr,x
  3352.    sta mp,x
  3353.    dex
  3354.    bpl -
  3355.    lda #<expTable
  3356.    ldy #>expTable
  3357.    sta zp+0
  3358.    sty zp+1
  3359.    lda expLength
  3360.    ldy #0
  3361.    jsr stash
  3362.    rts
  3363.  
  3364. fillMhType : buf 1
  3365.  
  3366. fillMemoryHole = *  ;( .A=holeType, varPtr, idVal, idType )
  3367.    sta fillMhType
  3368.    bit debug
  3369.    bpl fillMhCont
  3370.    lda #<fillMhMsg1
  3371.    ldy #>fillMhMsg1
  3372.    jsr puts
  3373.    lda varPtr+1
  3374.    jsr puthex
  3375.    lda varPtr+0
  3376.    jsr puthex
  3377.    lda #<fillMhMsg2
  3378.    ldy #>fillMhMsg2
  3379.    jsr puts
  3380.    ldx #idVal
  3381.    jsr putnum
  3382.    lda #" "
  3383.    jsr putchar
  3384.    lda #"("
  3385.    jsr putchar
  3386.    lda #"v"
  3387.    ldx idType
  3388.    beq +
  3389.    lda #"a"
  3390. +  jsr putchar
  3391.    lda #<fillMhMsg3
  3392.    ldy #>fillMhMsg3
  3393.    jsr puts
  3394.    lda fillMhType
  3395.    jsr puthex
  3396.    lda #chrCR
  3397.    jsr putchar
  3398.    ;%%%
  3399.  
  3400.    fillMhCont = *
  3401.    lda fillMhType
  3402.    cmp #$40
  3403.    beq fillMhBranch
  3404.    tax
  3405.    dex
  3406. -  lda idVal,x
  3407.    sta memPutVals,x
  3408.    dex
  3409.    bpl -
  3410.    ldx fillMhType
  3411.    dex
  3412. -  inx
  3413.    cpx #4
  3414.    bcs +
  3415.    lda idVal,x
  3416.    beq -
  3417.    lda #errValueTooLarge
  3418.    jmp errorRef
  3419. +  lda fillMhType
  3420.    ldx varPtr+0
  3421.    ldy varPtr+1
  3422.    jsr memPut
  3423.    ;** add relocatable reference
  3424.    lda idType
  3425.    beq +
  3426.    cmp #$04
  3427.    bcs +
  3428.    ldx varPtr+0
  3429.    ldy varPtr+1
  3430.    jsr recordRelocRef
  3431. +  rts
  3432.  
  3433.    fillMhBranch = *
  3434.    lda idVal+2
  3435.    ora idVal+3
  3436.    beq +
  3437.    lda #errValueTooLarge
  3438.    jmp errorRef
  3439. +  clc
  3440.    lda varPtr+0
  3441.    adc #1
  3442.    sta memPutVals+0
  3443.    lda varPtr+1
  3444.    adc #0
  3445.    sta memPutVals+1
  3446.    sec
  3447.    lda idVal+0
  3448.    sbc memPutVals+0
  3449.    sta memPutVals+0
  3450.    tax
  3451.    lda idVal+1
  3452.    sbc memPutVals+1
  3453.    sta memPutVals+1
  3454.    cmp #0
  3455.    bne +
  3456.    cpx #128
  3457.    bcc ++
  3458. -  lda #errBranchTooFar
  3459.    jmp error
  3460. +  cmp #$ff
  3461.    bne -
  3462.    cpx #128
  3463.    bcc -
  3464. +  lda #1
  3465.    ldx varPtr+0
  3466.    ldy varPtr+1
  3467.    jsr memPut
  3468.    rts
  3469.  
  3470. fillMhMsg1 = *
  3471.    db "fill memory hole: address=$"
  3472.    db 0
  3473. fillMhMsg2 = *
  3474.    db ", value="
  3475.    db 0
  3476. fillMhMsg3 = *
  3477.    db "), holeType=$"
  3478.    db 0
  3479.  
  3480. ;======== program memory storage ========
  3481.  
  3482. memInit = *  ;( )
  3483.    lda #aceMemNull
  3484.    sta memBufPtr+3
  3485.    ldx #0
  3486.    lda #aceMemNull
  3487. -  sta memPtrTable,x
  3488.    inx
  3489.    bne -
  3490.    rts
  3491.  
  3492. memPutSave : buf 2
  3493.  
  3494. memPut = *  ;( .XY=addr,.A=byteCount, memPutVals )
  3495.    sta memPutCount
  3496.    sty memPutPage
  3497.    ldy #0
  3498.  
  3499.    memPutNext = *
  3500.    lda memBufPtr+3
  3501.    cmp #aceMemNull
  3502.    beq memPutMiss
  3503.    lda memPutPage
  3504.    cmp memBufPage
  3505.    bne memPutMiss
  3506.    lda memPutVals,y
  3507.    sta memBuf,x
  3508.    inx
  3509.    bne +
  3510.    inc memPutPage
  3511. +  iny
  3512.    cpy memPutCount
  3513.    bcc memPutNext
  3514.    rts
  3515.  
  3516.    memPutMiss = *
  3517.    stx memPutSave+0
  3518.    sty memPutSave+1
  3519.    jsr memFlushBuf
  3520.    jsr memFetchBuf
  3521.    ldx memPutSave+0
  3522.    ldy memPutSave+1
  3523.    jmp memPutNext
  3524.  
  3525. memFlushBuf = *
  3526.    lda #<memBuf
  3527.    ldy #>memBuf
  3528.    sta zp+0
  3529.    sty zp+1
  3530.    ;** flush old page
  3531.    ldx #3
  3532. -  lda memBufPtr,x
  3533.    sta mp,x
  3534.    dex
  3535.    bpl -
  3536.    lda mp+3
  3537.    cmp #aceMemNull
  3538.    beq +
  3539.    lda memBufPage
  3540.    and #$03
  3541.    clc
  3542.    adc mp+1
  3543.    sta mp+1
  3544.    lda #0
  3545.    ldy #1
  3546.    jsr stash
  3547. +  rts
  3548.  
  3549. memFetchBuf = *  ;( memPutPage )
  3550.    lda #<memBuf
  3551.    ldy #>memBuf
  3552.    sta zp+0
  3553.    sty zp+1
  3554.    lda memPutPage
  3555.    sta memBufPage
  3556.    and #%11111100
  3557.    tay
  3558.    ldx #0
  3559. -  lda memPtrTable,y
  3560.    sta memBufPtr,x
  3561.    sta mp,x
  3562.    iny
  3563.    inx
  3564.    cpx #4
  3565.    bcc -
  3566.    lda mp+3
  3567.    cmp #aceMemNull
  3568.    beq memFetchBufNew
  3569.    lda memPutPage
  3570.    and #$03
  3571.    clc
  3572.    adc mp+1
  3573.    sta mp+1
  3574.    lda #0
  3575.    ldy #1
  3576.    jsr fetch
  3577.    rts
  3578.    
  3579.    memFetchBufNew = *
  3580.    lda #0
  3581.    ldy #4
  3582.    jsr malloc
  3583.    lda memBufPage
  3584.    and #%11111100
  3585.    tay
  3586.    ldx #0
  3587. -  lda mp,x
  3588.    sta memPtrTable,y
  3589.    sta memBufPtr,x
  3590.    iny
  3591.    inx
  3592.    cpx #4
  3593.    bcc -
  3594.    rts
  3595.  
  3596. memSaveAddr : buf 2
  3597. memSaveFd   : buf 1
  3598. memSaveLen  : buf 1  ;0==256
  3599.  
  3600. memSave = *  ;( .A=fd, .XY=from, address=to)
  3601.    sta memSaveFd
  3602.    stx memSaveAddr+0
  3603.    sty memSaveAddr+1
  3604.    jsr memFlushBuf
  3605.  
  3606.    memSaveNext = *
  3607.    lda memSaveAddr+0
  3608.    cmp address+0
  3609.    lda memSaveAddr+1
  3610.    sbc address+1
  3611.    bcc +
  3612.    rts
  3613. +  lda memSaveAddr+1
  3614.    sta memPutPage
  3615.    jsr memFetchBuf   ;sets (zp)
  3616.    lda #0
  3617.    sta memSaveLen
  3618.    ;** set bottom
  3619.    lda memSaveAddr+0
  3620.    beq ++
  3621.    clc
  3622.    lda zp+0
  3623.    adc memSaveAddr+0
  3624.    sta zp+0
  3625.    bcc +
  3626.    inc zp+1
  3627. +  sec
  3628.    lda memSaveLen
  3629.    sbc memSaveAddr+0
  3630.    sta memSaveLen
  3631.    ;** set top
  3632. +  lda memSaveAddr+1
  3633.    cmp address+1
  3634.    bcc +
  3635.    sec
  3636.    lda #0
  3637.    sbc address+0
  3638.    tax
  3639.    lda memSaveLen
  3640.    stx memSaveLen
  3641.    sec
  3642.    sbc memSaveLen
  3643.    sta memSaveLen
  3644.    ;** save the page
  3645. +  ldy #0
  3646.    lda memSaveLen
  3647.    bne +
  3648.    iny
  3649. +  ldx memSaveFd
  3650.    jsr write
  3651.    lda memSaveLen
  3652.    beq +
  3653.    clc
  3654.    adc memSaveAddr+0
  3655.    sta memSaveAddr+0
  3656.    bcc ++
  3657. +  inc memSaveAddr+1
  3658. +  jmp memSaveNext
  3659.  
  3660. recordRelocRef = *  ;( .XY=refAddress, .A=valueType )
  3661.    rts
  3662.  
  3663. ;======== tokenizer ========
  3664.  
  3665. ;* fill entire buffer, pad with spaces; .CS=eof
  3666. fillbuf = *
  3667.    lda #<sourceBuf
  3668.    ldy #>sourceBuf
  3669.    sta zp
  3670.    sty zp+1
  3671.    lda #0
  3672.    ldy #1
  3673.    sta bufptr
  3674.    ldx sourceFcb
  3675.    jsr read
  3676.    bne +
  3677.    sec
  3678.    rts
  3679. +  cpy #1
  3680.    bcc +
  3681.    clc
  3682.    rts
  3683. +  tay
  3684.    lda #" "
  3685. -  sta sourceBuf,y
  3686.    iny
  3687.    bne -
  3688.    clc
  3689.    rts
  3690.  
  3691. getNextChar = *
  3692.    inc bufptr
  3693.    beq +
  3694. -  ldy bufptr
  3695.    lda sourceBuf,y
  3696.    rts
  3697. +  jsr fillbuf
  3698.    bcc -
  3699.    lda #chrEOF
  3700.    rts
  3701.  
  3702. eatWhitespace = *  ;() : .A=NextChar
  3703.    lda prevChar
  3704.    cmp #" "
  3705.    beq +
  3706.    cmp #chrTab
  3707.    beq +
  3708.    rts
  3709. +  ldy bufptr
  3710. -  iny
  3711.    beq +
  3712.    eatWhCont = *
  3713.    lda sourceBuf,y
  3714.    cmp #" "
  3715.    beq -
  3716.    cmp #chrTab
  3717.    beq -
  3718.    sty bufptr
  3719.    rts
  3720. +  jsr fillbuf
  3721.    bcs +
  3722.    ldy #0
  3723.    jmp eatWhCont
  3724. +  lda #chrEOF
  3725.    rts
  3726.  
  3727. ;*** token dispatch ***
  3728. ;ret: .X=tokenIdentifier, .A=nextChar, .Y=strlen, stringLen, stringBuf
  3729. ;     .X=tokenNumber,     .Y=numlen, number
  3730. ;     .X=tokenString,     .A=firstChar,.Y=strlen, stringLen, stringBuf
  3731. ;     .X=tokenSpecial,    .A=char
  3732.  
  3733. tokDebugSave : buf 3
  3734.  
  3735. getToken = *
  3736.    lda newCol
  3737.    sta sourceCol
  3738.    lda newLine+0
  3739.    sta sourceLine+0
  3740.    lda newLine+1
  3741.    sta sourceLine+1
  3742.    lda newLine+2
  3743.    sta sourceLine+2
  3744.    lda newLine+3
  3745.    sta sourceLine+3
  3746.    bit debug
  3747.    bpl getTokenReal
  3748.    jsr getTokenReal
  3749.    sta tokDebugSave+0
  3750.    stx tokDebugSave+1
  3751.    sty tokDebugSave+2
  3752.    jsr dispToken
  3753.    lda tokDebugSave+0
  3754.    ldx tokDebugSave+1
  3755.    ldy tokDebugSave+2
  3756.    rts
  3757.  
  3758. getTokenReal = *
  3759.    lda prevChar
  3760.    cmp #" "
  3761.    bne +
  3762. -  jsr eatWhitespace
  3763. +  cmp #chrTab
  3764.    beq -
  3765.    cmp #"@"
  3766.    bcc +
  3767.    jmp getIdentifier
  3768. +  cmp #"'"
  3769.    bcc cmpMore1
  3770.    bne +
  3771.    jmp getString
  3772. +  cmp #"0"
  3773.    bcc tokSpecial
  3774.    cmp #":"
  3775.    bcs +
  3776.  
  3777.    tokNum = *
  3778.    jmp getNumber
  3779.  
  3780. +  cmp #";"
  3781.    bne +
  3782.    jmp eatComment
  3783.  
  3784.    tokSpecial = *
  3785.    jmp getSpecialToken
  3786.  
  3787.    cmpMore1 = *
  3788.    cmp #"$"
  3789.    bcc +
  3790.    beq tokNum
  3791.    cmp #"%"
  3792.    beq tokNum
  3793.    jmp getSpecialToken
  3794.  
  3795. +  cmp #chrQuote
  3796.    bne tokSpecial
  3797.    jmp getString
  3798.  
  3799. ;*** comment ***
  3800.  
  3801. eatComment = *
  3802.    ldy bufptr
  3803. -  iny
  3804.    beq +
  3805.  
  3806.    commentChar = *
  3807.    lda sourceBuf,y
  3808.    cmp #chrCR
  3809.    bne -
  3810.    sty bufptr
  3811.    jmp getSpecialToken
  3812. +  jsr fillbuf
  3813.    bcs +
  3814.    ldy #0
  3815.    beq commentChar
  3816. +  lda #chrEOF
  3817.    jmp getSpecialToken
  3818.  
  3819. ;*** special ***
  3820.  
  3821. getSpecialToken = *
  3822.    cmp #chrCR
  3823.    bne +
  3824.    inc newLine+0
  3825.    bne +
  3826.    inc newLine+1
  3827.    bne +
  3828.    inc newLine+2
  3829.    bne +
  3830.    inc newLine+3
  3831. +  cmp #chrEOF
  3832.    bne +
  3833.    sta prevChar
  3834.    sta tokenChar
  3835.    ldx #tokenEOF
  3836.    stx tokenType
  3837.    rts
  3838. +  pha
  3839.    jsr getNextChar
  3840.    sta prevChar
  3841.    sta tokenNextChar
  3842.    pla
  3843.    ldx #tokenSpecial
  3844.    stx tokenType
  3845.    sta tokenChar
  3846.    rts
  3847.  
  3848. ;*** identifier ***
  3849.  
  3850. getIdentifier = *
  3851.    sta stringBuf
  3852.    ldy #1
  3853.    sty stringLen
  3854. -  jsr getNextChar
  3855.    cmp #"@"
  3856.    bcc identExit
  3857.  
  3858.    identGoodChar = *
  3859.    ldy stringLen
  3860.    sta stringBuf,y
  3861.    inc stringLen
  3862.    cpy #240
  3863.    bcc -
  3864.    sta prevChar
  3865.    lda #errIdentTooLong
  3866.    jmp error
  3867.  
  3868.    identExit = *
  3869.    cmp #"."
  3870.    beq identGoodChar
  3871.    cmp #"_"
  3872.    beq identGoodChar
  3873.    cmp #"0"
  3874.    bcc +
  3875.    cmp #":"
  3876.    bcc identGoodChar
  3877. +  cmp #" "
  3878.    bne +
  3879. -  sta prevChar
  3880.    jsr eatWhitespace
  3881. +  cmp #chrTab
  3882.    beq -
  3883.    sta prevChar
  3884.    lda #0
  3885.    ldy stringLen
  3886.    sta stringBuf,y
  3887.    lda prevChar
  3888.    ldy stringLen
  3889.    ldx #tokenIdentifier
  3890.    stx tokenType
  3891.    cmp #";"
  3892.    bne +
  3893.    lda #chrCR
  3894. +  sta tokenNextChar
  3895.    rts
  3896.  
  3897. ;*** string ***
  3898.  
  3899. getString = *
  3900.    sta strDelimit
  3901.    lda #0
  3902.    sta stringLen
  3903. -  jsr getNextChar
  3904.    sta prevChar
  3905.    cmp #chrEOF
  3906.    beq strEof
  3907.    cmp strDelimit
  3908.    beq strExit
  3909.    cmp #chrCR
  3910.    beq strEof
  3911.    cmp #"\\"
  3912.    beq strEsc
  3913.    getStrPut = *
  3914.    ldy stringLen
  3915.    sta stringBuf,y
  3916.    inc stringLen
  3917.    lda stringLen
  3918.    cmp #241
  3919.    bcc -
  3920.    sta prevChar
  3921.    lda #errStringTooLong
  3922.    jmp error
  3923.  
  3924. strEsc = *
  3925.    jsr getNextChar
  3926.    cmp #chrCR
  3927.    beq strEof
  3928.    cmp #chrEOF
  3929.    beq strEof
  3930.    ldx #strEscCharEnd-strEscChar-1
  3931. -  cmp strEscChar,x
  3932.    beq +
  3933.    dex
  3934.    bpl -
  3935.    jmp getStrPut
  3936. +  lda strEscTrans,x
  3937.    jmp getStrPut
  3938.  
  3939. strEscChar = *
  3940.    db "\\nbtraz'e0q"
  3941.    db chrQuote
  3942.    strEscCharEnd = *
  3943. strEscTrans = *
  3944.    db 92,13,20,9,10,7,0,39,27,0,34,34
  3945.  
  3946. strEof = *
  3947.    lda #errNoCloseQuote
  3948.    jmp error
  3949.  
  3950. strExit = *
  3951.    jsr getNextChar
  3952.    sta prevChar
  3953.    lda #0  ;but may contain \0
  3954.    ldy stringLen
  3955.    sta stringBuf,y
  3956.    lda stringBuf+0
  3957.    ldx #tokenString
  3958.    stx tokenType
  3959.    sta tokenChar
  3960.    rts
  3961.  
  3962. getNumber = *
  3963.    pha
  3964.    ldx #3
  3965.    lda #0
  3966. -  sta number,x
  3967.    dex
  3968.    bpl -
  3969.    pla
  3970.    ldx #16
  3971.    cmp #"$"
  3972.    beq +
  3973.    ldx #2
  3974.    cmp #"%"
  3975.    beq +
  3976.    ldx #10
  3977.    stx numBase
  3978.    bne gotNextDigit
  3979. +  stx numBase
  3980.    jsr getNextChar
  3981.    sta prevChar
  3982.    jsr checkDigit
  3983.    bcc +
  3984.    lda #errBadNumber
  3985.    jmp error
  3986. +  txa
  3987.    jmp gotNextDigit
  3988.  
  3989. nextDigit = *
  3990.    jsr getNextChar
  3991.    sta prevChar
  3992.    cmp #"_"
  3993.    beq nextDigit
  3994. gotNextDigit = *
  3995.    jsr checkDigit
  3996.    bcs getNumExit
  3997.    pha
  3998.    jsr shiftNumber
  3999.    bcs overflowExitPla
  4000.    pla
  4001.    clc
  4002.    adc number
  4003.    sta number
  4004.    bcc +
  4005.    inc number+1
  4006.    bne +
  4007.    inc number+2
  4008.    bne +
  4009.    inc number+3
  4010.    beq overflowExit
  4011. +  jmp nextDigit
  4012.  
  4013. overflowExitPla = *
  4014.    pla
  4015. overflowExit = *
  4016.    lda #errNumOverflow
  4017.    jmp error
  4018.  
  4019. getNumExit = *
  4020.    ldy #3
  4021. -  lda number,y
  4022.    beq +
  4023.    dey
  4024.    bpl -
  4025.    iny
  4026. +  iny
  4027.    sty tokenNumBytes
  4028.    ldx #tokenNumber
  4029.    stx tokenType
  4030.    rts
  4031.  
  4032. checkDigit = *  ;( .A=asciiDigit ) : .A=binDigit, .X=asciiDigit, .CC=ok
  4033.    tax
  4034.    cmp #"0"
  4035.    bcc checkBad
  4036.    cmp #"9"+1
  4037.    bcc checkAnd
  4038.    cmp #"a"
  4039.    bcc checkBad
  4040.    cmp #"f"+1
  4041.    bcc +
  4042.    cmp #"A"
  4043.    bcc checkBad
  4044.    cmp #"F"+1
  4045.    bcs checkBad
  4046. +  sec
  4047.    sbc #7
  4048.    checkAnd = *
  4049.    and #$0f
  4050.    cmp numBase
  4051.    rts
  4052.    checkBad = *
  4053.    sec
  4054.    rts
  4055.  
  4056. shiftNumber = *
  4057.    lda numBase
  4058.    cmp #10
  4059.    bne +
  4060.    ldx #3
  4061. -  lda number,x
  4062.    sta numSave,x
  4063.    dex
  4064.    bpl -
  4065.    ldx #2
  4066.    jsr rollNumber
  4067.    jsr addNumber
  4068.    ldx #1
  4069.    jsr rollNumber
  4070.    rts
  4071. +  ldx #1
  4072.    cmp #16
  4073.    bne +
  4074.    ldx #4
  4075. +  jsr rollNumber
  4076.    rts
  4077.  
  4078.    rollNumber = *  ;( .X=times )
  4079.    asl number
  4080.    rol number+1
  4081.    rol number+2
  4082.    rol number+3
  4083.    bcs +
  4084.    dex
  4085.    bne rollNumber
  4086.    rts
  4087. +  pla
  4088.    pla
  4089.    sec
  4090.    rts
  4091.  
  4092.    addNumber = *
  4093.    ldx #0
  4094.    clc
  4095. -  lda number,x
  4096.    adc numSave,x
  4097.    sta number,x
  4098.    inx
  4099.    txa
  4100.    and #$03
  4101.    bne -
  4102.    bcs +
  4103.    rts
  4104. +  pla
  4105.    pla
  4106.    sec
  4107.    rts
  4108.  
  4109. ;======== debugging token display routines ========
  4110.  
  4111. dispToken = *  ;( .tokenType )
  4112.    ldx tokenType
  4113.    cpx #tokenIdentifier
  4114.    beq dispIdentifier
  4115.    cpx #tokenString
  4116.    beq dispString
  4117.    cpx #tokenSpecial
  4118.    bne +
  4119.    jmp dispSpecial
  4120. +  cpx #tokenNumber
  4121.    bne +
  4122.    jmp dispNumber
  4123. +  rts
  4124.  
  4125. dispIdentifier = *
  4126.    lda #"i"
  4127.    jsr putchar
  4128.    lda #":"
  4129.    jsr putchar
  4130.    jsr showStr
  4131.    lda #","
  4132.    jsr putchar
  4133.    jsr hash
  4134.    lda #0
  4135.    sta number+2
  4136.    sta number+3
  4137.    lda hashVal+0
  4138.    ldy hashVal+1
  4139.    sta number+0
  4140.    sty number+1
  4141.    ldx #number
  4142.    jsr putnum
  4143.    lda #","
  4144.    jsr putchar
  4145.    sec
  4146.    lda hashPtr+0
  4147.    sbc #<identHashTable
  4148.    sta number+0
  4149.    lda hashPtr+1
  4150.    sbc #>identHashTable
  4151.    sta number+1
  4152.    lsr number+1
  4153.    ror number+0
  4154.    lsr number+1
  4155.    ror number+0
  4156.    ldx #number
  4157.    jsr putnum
  4158.    lda #","
  4159.    jsr putchar
  4160.    lda tokenNextChar
  4161.    showChar = *
  4162.    cmp #chrCR
  4163.    bne +
  4164.    lda #"\\"
  4165.    jsr putchar
  4166.    lda #"n"
  4167. +  jsr putchar
  4168.    showCR = *
  4169.    lda #chrCR
  4170.    jsr putchar
  4171.    rts
  4172.  
  4173. dispString = *
  4174.    lda #"s"
  4175.    jsr putchar
  4176.    lda #":"
  4177.    jsr putchar
  4178.    jsr showStr
  4179.    jmp showCR
  4180.  
  4181. showStr = *
  4182.    lda #<stringBuf
  4183.    ldy #>stringBuf
  4184.    sta zp+0
  4185.    sty zp+1
  4186.    lda stringLen
  4187.    ldy #0
  4188.    ldx #stdout
  4189.    jsr write
  4190.    rts
  4191.  
  4192. dispSpecial = *
  4193.    lda #"c"
  4194.    jsr putchar
  4195.    lda #":"
  4196.    jsr putchar
  4197.    lda tokenChar
  4198.    jmp showChar
  4199.  
  4200. dispNumber = *
  4201.    lda #"n"
  4202.    jsr putchar
  4203.    lda #":"
  4204.    jsr putchar
  4205.    lda #<stringBuf
  4206.    ldy #>stringBuf
  4207.    sta zp+0
  4208.    sty zp+1
  4209.    ldx #number
  4210.    lda #1
  4211.    jsr utoa
  4212.    sty stringLen
  4213.    jsr showStr
  4214.    jmp showCR
  4215.  
  4216. ;=== dynamic memory routines ===
  4217.  
  4218. mallocWork = memWork ;(16)  ;required work area; defined earlier
  4219.  
  4220. mallocHead   : buf 4
  4221. tpaFreeFirst : buf 1
  4222. tpaFreeMin   : buf 1
  4223. tpaFreePages : buf 1
  4224. tpaAreaStart : buf 1
  4225. tpaAreaEnd   : buf 1
  4226.  
  4227. ;*** mallocInit()
  4228.  
  4229. mallocInit = *
  4230.    lda #aceMemNull
  4231.    sta mallocHead+3
  4232.    ldx #0
  4233.    lda #$ff
  4234. -  sta tpaFreemap,x
  4235.    inx
  4236.    bne -
  4237.    ldx #>bssEnd
  4238.    lda #<bssEnd
  4239.    beq +
  4240.    inx
  4241. +  stx tpaFreeFirst
  4242.    stx tpaAreaStart
  4243.    ldx aceMemTop+1
  4244.    stx mallocWork
  4245.    stx tpaAreaEnd
  4246.    txa
  4247.    sec
  4248.    sbc tpaFreeFirst
  4249.    bcs +
  4250.    lda #0
  4251. +  sta tpaFreePages
  4252.    clc
  4253.    adc #1
  4254.    sta tpaFreeMin
  4255.    ldx tpaFreeFirst
  4256.    cpx mallocWork
  4257.    bcs +
  4258.    lda #$00
  4259. -  sta tpaFreemap,x
  4260.    inx
  4261.    cpx mallocWork
  4262.    bcc -
  4263. +  rts
  4264.  
  4265. libPages : buf 1
  4266.  
  4267. libPageAlloc = *  ;( .A=pages ) : [mp]
  4268.    sta libPages
  4269.    ldx #$00
  4270.    ldy #aceMemInternal-1
  4271.    jsr pagealloc
  4272.    bcs +
  4273.    rts
  4274. +  jsr tpaPageAlloc
  4275.    bcs +
  4276.    rts
  4277. +  lda libPages
  4278.    ldx #aceMemInternal
  4279.    ldy #$ff
  4280.    jsr pagealloc
  4281.    bcs +
  4282.    rts
  4283. +  sec
  4284.    ;rts
  4285.    ;lda #<nomemMsg
  4286.    ;ldy #>nomemMsg
  4287.    ;jsr eputs
  4288.    lda #errInsufficientMemory
  4289.    jmp error
  4290.  
  4291.    ;nomemMsg = *
  4292.    ;db chrCR
  4293.    ;db "Insufficient memory, aborting."
  4294.    ;db chrCR,0
  4295.  
  4296. newmax   : buf 1
  4297.  
  4298. tpaPageAlloc = *  ;( libPages ) : [mp]
  4299.    lda libPages
  4300.    cmp tpaFreeMin
  4301.    bcs tpaFreemapFull
  4302.    ;** first free
  4303.    ldx tpaFreeFirst
  4304.    lda tpaFreemap,x
  4305.    beq ++
  4306. -  inx
  4307.    beq tpaFreemapFull
  4308.    lda tpaFreemap,x
  4309.    bne -
  4310.    stx tpaFreeFirst
  4311.    jmp ++
  4312.    tpaFreemapFull = *
  4313.    lda libPages
  4314.    cmp tpaFreeMin
  4315.    bcs +
  4316.    sta tpaFreeMin
  4317. +  sec
  4318.    rts
  4319.  
  4320.    ;** search
  4321. +  dex
  4322. -  ldy libPages
  4323. -  inx
  4324.    beq tpaFreemapFull
  4325.    lda tpaFreemap,x
  4326.    bne --
  4327.    dey
  4328.    bne -
  4329.  
  4330.    ;** allocate
  4331.    stx newmax
  4332.    ldy libPages
  4333.    lda #$41
  4334. -  sta tpaFreemap,x
  4335.    dex
  4336.    dey
  4337.    bne -
  4338.    inx
  4339.    cpx tpaFreeFirst
  4340.    bne +
  4341.    ldy newmax
  4342.    iny
  4343.    sty tpaFreeFirst
  4344. +  sec
  4345.    lda tpaFreePages
  4346.    sbc libPages
  4347.    sta tpaFreePages
  4348.    lda #0
  4349.    ldy #aceMemInternal
  4350.    sta mp+0
  4351.    stx mp+1
  4352.    sta mp+2
  4353.    sty mp+3
  4354.    clc
  4355.    rts
  4356.  
  4357. mallocLenSave : buf 3
  4358.  
  4359. malloc = *
  4360. quickMalloc = *
  4361.    sta mallocLenSave+0
  4362.    sty mallocLenSave+1
  4363.    jsr libMalloc
  4364.    bcs +
  4365.    rts
  4366. +  ldx mallocLenSave+1
  4367.    lda mallocLenSave+0
  4368.    beq +
  4369.    inx
  4370. +  txa
  4371.    cpx #>1024
  4372.    bcs +
  4373.    ldx #>1024
  4374. +  txa
  4375.    sta mallocLenSave+2
  4376.    jsr libPageAlloc
  4377.    bcc +
  4378.    rts
  4379. +  lda #0
  4380.    ldy mallocLenSave+2
  4381.    jsr free
  4382.    lda mallocLenSave+0
  4383.    ldy mallocLenSave+1
  4384.    jmp malloc
  4385.  
  4386. ;*** malloc( .AY=Bytes ) : [mp]=FarPointer
  4387.  
  4388. mallocMemNextPtr = mallocWork+0 ;(4)
  4389. mallocMemLength  = mallocWork+4 ;(2)
  4390. mallocLength     = mallocWork+6 ;(2)
  4391. mallocQ          = mallocWork+8 ;(4)
  4392.  
  4393. libMalloc = *
  4394.    clc
  4395.    adc #7
  4396.    bcc +
  4397.    iny
  4398. +  and #$f8
  4399.    sta mallocLength
  4400.    sty mallocLength+1
  4401.    ldx #3
  4402. -  lda mallocHead,x
  4403.    sta mp,x
  4404.    lda #aceMemNull
  4405.    sta mallocQ,x
  4406.    dex
  4407.    bpl -
  4408.  
  4409.    mallocLook = *
  4410.    lda mp+3
  4411.    cmp #aceMemNull
  4412.    bne +
  4413.  
  4414.    mallocErrorExit = *
  4415.    lda #aceMemNull
  4416.    sta mp+3
  4417.    lda #aceErrInsufficientMemory
  4418.    sta errno
  4419.    sec
  4420.    rts
  4421.  
  4422. +  ldx #mallocMemNextPtr
  4423.    ldy #6
  4424.    jsr zpload
  4425.    lda mallocMemLength
  4426.    cmp mallocLength
  4427.    lda mallocMemLength+1
  4428.    sbc mallocLength+1
  4429.    bcs mallocGotBlock
  4430.    ldx #3
  4431. -  lda mp,x
  4432.    sta mallocQ,x
  4433.    lda mallocMemNextPtr,x
  4434.    sta mp,x
  4435.    dex
  4436.    bpl -
  4437.    jmp mallocLook
  4438.  
  4439.    mallocGotBlock = *
  4440.    lda mallocMemLength
  4441.    cmp mallocLength
  4442.    bne +
  4443.    lda mallocMemLength+1
  4444.    sbc mallocLength+1
  4445.    beq mallocTakeWholeBlock
  4446. +  sec
  4447.    lda mallocMemLength
  4448.    sbc mallocLength
  4449.    sta mallocMemLength
  4450.    lda mallocMemLength+1
  4451.    sbc mallocLength+1
  4452.    sta mallocMemLength+1
  4453.    ldx #mallocMemNextPtr
  4454.    ldy #6
  4455.    jsr zpstore
  4456.    clc
  4457.    lda mp+0
  4458.    adc mallocMemLength
  4459.    sta mp+0
  4460.    lda mp+1
  4461.    adc mallocMemLength+1
  4462.    sta mp+1
  4463.    clc
  4464.    rts
  4465.  
  4466.    mallocTakeWholeBlock = *
  4467.    lda mallocQ+3
  4468.    cmp #aceMemNull
  4469.    bne +
  4470.    ldx #3
  4471. -  lda mallocMemNextPtr,x
  4472.    sta mallocHead,x
  4473.    dex
  4474.    bpl -
  4475.    clc
  4476.    rts
  4477. +  ldx #3
  4478. -  lda mp,x
  4479.    ldy mallocQ,x
  4480.    sta mallocQ,x
  4481.    sty mp,x
  4482.    dex
  4483.    bpl -
  4484.    ldx #mallocMemNextPtr
  4485.    ldy #4
  4486.    jsr zpstore
  4487.    ldx #3
  4488. -  lda mallocQ,x
  4489.    sta mp,x
  4490.    dex
  4491.    bpl -
  4492.    clc
  4493.    rts
  4494.  
  4495. ;*** free( [mp]=FarPointer, .AY=Length )  {alters [mp]}
  4496.  
  4497. freeMemNextPtr = mallocWork+0  ;(4)
  4498. freeMemLength  = mallocWork+4  ;(2)
  4499. freeLength     = mallocWork+6  ;(2)
  4500. freeNewPtr     = mallocWork+8  ;(4)
  4501. freeQ          = mallocWork+12 ;(4)
  4502.  
  4503. free = *
  4504.    clc
  4505.    adc #7
  4506.    bcc +
  4507.    iny
  4508. +  and #$f8
  4509.    sta freeLength+0
  4510.    sty freeLength+1
  4511.    ldx #3
  4512. -  lda mp,x
  4513.    sta freeNewPtr,x
  4514.    lda mallocHead,x
  4515.    sta mp,x
  4516.    lda #aceMemNull
  4517.    sta freeQ,x
  4518.    dex
  4519.    bpl -
  4520.  
  4521.    freeSearchLoop = *
  4522.    lda mp+3
  4523.    cmp #aceMemNull
  4524.    beq freeCoalesceQandNew
  4525.    lda mp+0
  4526.    cmp freeNewPtr+0
  4527.    lda mp+1
  4528.    sbc freeNewPtr+1
  4529.    lda mp+2
  4530.    sbc freeNewPtr+2
  4531.    lda mp+3
  4532.    sbc freeNewPtr+3
  4533.    bcs freeCoalesceQandNew
  4534. +  ldx #freeMemNextPtr
  4535.    ldy #4
  4536.    jsr zpload
  4537.    ldx #3
  4538. -  lda mp,x
  4539.    sta freeQ,x
  4540.    lda freeMemNextPtr,x
  4541.    sta mp,x
  4542.    dex
  4543.    bpl -
  4544.    bmi freeSearchLoop
  4545.  
  4546.    freeCoalesceQandNew = *
  4547.    ldx #3
  4548. -  lda freeQ,x
  4549.    sta mp,x
  4550.    dex
  4551.    bpl -
  4552.    lda mp+3
  4553.    cmp #aceMemNull
  4554.    bne +
  4555.    ;** prev is head
  4556.    ldx #3
  4557. -  lda mallocHead,x
  4558.    sta freeMemNextPtr,x
  4559.    lda freeNewPtr,x
  4560.    sta mallocHead,x
  4561.    dex
  4562.    bpl -
  4563.    lda freeLength+0
  4564.    ldy freeLength+1
  4565.    sta freeMemLength+0
  4566.    sty freeMemLength+1
  4567.    jmp freeCoalesceNewAndP
  4568.  
  4569.    ;** prev is real
  4570. +  ldx #freeMemNextPtr
  4571.    ldy #6
  4572.    jsr zpload
  4573.    lda mp+3
  4574.    cmp freeNewPtr+3
  4575.    bne +
  4576.    lda mp+2
  4577.    cmp freeNewPtr+2
  4578.    bne +
  4579.    clc
  4580.    lda mp+0
  4581.    adc freeMemLength
  4582.    tax
  4583.    lda mp+1
  4584.    adc freeMemLength+1
  4585.    cmp freeNewPtr+1
  4586.    bne +
  4587.    cpx freeNewPtr
  4588.    bne +
  4589.    ;** prev does coalesce
  4590.    clc
  4591.    lda freeMemLength
  4592.    adc freeLength
  4593.    sta freeMemLength
  4594.    lda freeMemLength+1
  4595.    adc freeLength+1
  4596.    sta freeMemLength+1
  4597.    ldx #3
  4598. -  lda freeQ,x
  4599.    sta freeNewPtr,x
  4600.    dex
  4601.    bpl -
  4602.    bmi freeCoalesceNewAndP
  4603.  
  4604.    ;** prev does not coalesce
  4605. +  ldx #freeNewPtr
  4606.    ldy #4
  4607.    jsr zpstore
  4608.    lda freeLength+0
  4609.    ldy freeLength+1
  4610.    sta freeMemLength+0
  4611.    sty freeMemLength+1
  4612.  
  4613.    freeCoalesceNewAndP = *
  4614.    lda freeNewPtr+3
  4615.    cmp freeMemNextPtr+3
  4616.    bne +
  4617.    lda freeNewPtr+2
  4618.    cmp freeMemNextPtr+2
  4619.    bne +
  4620.    clc
  4621.    lda freeNewPtr
  4622.    adc freeMemLength
  4623.    tax
  4624.    lda freeNewPtr+1
  4625.    adc freeMemLength+1
  4626.    cmp freeMemNextPtr+1
  4627.    bne +
  4628.    cpx freeMemNextPtr
  4629.    bne +
  4630.  
  4631.    ;** new and next coalesce
  4632.    ldx #3
  4633. -  lda freeMemNextPtr,x
  4634.    sta mp,x
  4635.    dex
  4636.    bpl -
  4637.    lda freeMemLength+1
  4638.    pha
  4639.    lda freeMemLength+0
  4640.    pha
  4641.    ldx #freeMemNextPtr
  4642.    ldy #6
  4643.    jsr zpload
  4644.    clc
  4645.    pla
  4646.    adc freeMemLength+0
  4647.    sta freeMemLength+0
  4648.    pla
  4649.    adc freeMemLength+1
  4650.    sta freeMemLength+1
  4651.  
  4652. +  ldx #3
  4653. -  lda freeNewPtr,x
  4654.    sta mp,x
  4655.    dex
  4656.    bpl -
  4657.    ldx #freeMemNextPtr
  4658.    ldy #6
  4659.    jsr zpstore
  4660.    clc
  4661.    rts
  4662.  
  4663. ;======== standard library ========
  4664.  
  4665. eputs = *
  4666.    ldx #stderr
  4667.    jmp fputs
  4668. puts = *
  4669.    ldx #stdout
  4670. fputs = *
  4671.    sta zp+0
  4672.    sty zp+1
  4673. fputsZp = *
  4674.    ldy #$ff
  4675. -  iny
  4676.    lda (zp),y
  4677.    bne -
  4678.    tya
  4679.    ldy #0
  4680.    jmp write
  4681.  
  4682. putchar = *
  4683.    ldx #stdout
  4684. putc = *
  4685.    sta putcBuffer
  4686.    lda #<putcBuffer
  4687.    ldy #>putcBuffer
  4688.    sta zp+0
  4689.    sty zp+1
  4690.    lda #1
  4691.    ldy #0
  4692.    jmp write
  4693.    putcBuffer : buf 1
  4694.  
  4695. getarg = *
  4696.    sty zp+1
  4697.    asl
  4698.    sta zp+0
  4699.    rol zp+1
  4700.    clc
  4701.    lda aceArgv
  4702.    adc zp+0
  4703.    sta zp+0
  4704.    lda aceArgv+1
  4705.    adc zp+1
  4706.    sta zp+1
  4707.    ldy #0
  4708.    lda (zp),y
  4709.    tax
  4710.    iny
  4711.    lda (zp),y
  4712.    stx zp+0
  4713.    sta zp+1
  4714.    lda zp+0
  4715.    ldy zp+1
  4716.    rts
  4717.  
  4718. ;end of file + blank line
  4719.  
  4720.  
  4721. ;======== bss ========
  4722.  
  4723. bss = *
  4724. sourceBuf    = bss+0                  ;( 256 bytes)
  4725. stringBuf    = sourceBuf+256          ;( 256 bytes)
  4726. symBuf       = stringBuf+256          ;( 256 bytes)
  4727. symNext      = symBuf+0
  4728. symValue     = symBuf+4
  4729. symUnresOpnd = symBuf+8
  4730. symType      = symBuf+9
  4731. symClass     = symBuf+10
  4732. symNameLen   = symBuf+11
  4733. symName      = symBuf+12
  4734. symHash      = symBuf+254
  4735. expTable     = symBuf+256            ;( 256 bytes == 15 entries)
  4736. expHoleType  = expTable+0
  4737. expLength    = expTable+1
  4738. expUnresCnt  = expTable+2
  4739. expSrcCol    = expTable+3
  4740. expHoleAddr  = expTable+4
  4741. expSrcLine   = expTable+8
  4742. expSrcFile   = expTable+12
  4743. expField     = expTable+0
  4744. expOp        = expField+0
  4745. expType      = expField+1
  4746. expSign      = expField+2
  4747. expHiLo      = expField+3
  4748. expValue     = expField+4
  4749. expNextUnres = expField+8
  4750. expNextOpnd  = expField+12
  4751. expReserved  = expField+13
  4752. identHashTable = expTable+256      ;(4096 bytes == 1024 entries (ref:hTabPag)
  4753. memPtrTable  = identHashTable+4096 ;( 256 bytes == 64 entries)
  4754. memBuf       = memPtrTable+256    ;( 256 bytes)
  4755. writeName    = memBuf+256         ;(  20 bytes)
  4756. tpaFreemap   = writeName+20       ;( 256 bytes)
  4757. bssEnd       = tpaFreemap+256
  4758.