keep obj/symbol mcopy symbol.mac **************************************************************** * * Symbol Tables * * This module contains the subroutines used to create, search * and manipulate the symbol table. * **************************************************************** copy directPage **************************************************************** * * SymbolCommon - global data for the symbol table module * **************************************************************** * SymbolCommon privdata ; ; Symbol table entry ; symNext equ 0 pointer to the next symbol symAlpha equ 4 alphabetized list pointer symVal equ 8 value of the label (or ptr to expression) symSeg equ 12 segment number symFile equ 14 file number symData equ 16 data area number symExp equ 18 is the value an expression? symFlag equ 20 pass 1/2 resolved flags symPriv equ 22 is the symbol private? symLength equ 24 length attribute symType equ 26 type attribute symName equ 28 symbol name (p-string) symSize equ 28 size of a symbol, sans symbol name ; ; Constants ; hashSize equ 877 number of hash buckets blockSize equ 4096 symbol table blocking factor ; ; Symbol table variables ; alpha ds 4 head of alphabetized list hashDisp ds 2 disp in hash table; saved for efficiency poolPtr ds 4 ptr to next byte in symbol table pool poolSize ds 2 # of bytes left in the current pool table ds hashSize*4 symbol table end **************************************************************** * * AllocatePool - allocate a new symbol table pool * * Outputs: * poolPtr - pointer to the first byte of the pool * poolSize - size of the block, in bytes * **************************************************************** * AllocatePool private using SymbolCommon ph4 #blockSize jsr MLalloc sta poolPtr stx poolPtr+2 lda #blockSize sta poolSize rts end **************************************************************** * * AlphaInsert - insert the symbol in the alphabetized list * * Inputs: * sym - pointer to the new symbol * alpha - head of the alphabetized list * **************************************************************** * AlphaInsert private using SymbolCommon p1 equ 1 work pointers p2 equ 5 p3 equ 9 sub (4:sym),12 lda alpha if alpha = nil then ora alpha+2 bne lb1 move4 sym,alpha alpha = sym ldy #symAlpha sym^.alpha = nil lda #0 sta [sym],Y iny iny sta [sym],Y brl lb8 return lb1 move4 alpha,p1 p1 = alpha stz p2 p2 = nil stz p2+2 add4 sym,#symName while sym^.symName >= p1^.symName do lda [sym] and #$00FF sta len1 lb2 add4 p1,#symName,p3 lda len1 sta lens lda [p3] and #$00FF sta len2 cmp lens bge lb3 sta lens lb3 short M ldy #1 lb4 lda [sym],Y cmp [p3],Y bne lb5 iny dec lens bne lb4 lda len1 cmp len2 lb5 long M blt lb6 move4 p1,p2 p2 = p1 ldy #symAlpha p1 = p2^.symAlpha lda [p2],Y sta p1 iny iny lda [p2],Y sta p1+2 ora p1 quit if at the end of the list bne lb2 endwhile lb6 sub4 sym,#symName fix sym ldy #symAlpha sym^.symAlpha = p1 lda p1 sta [sym],Y iny iny lda p1+2 sta [sym],Y lda p2 if p2 = nil then ora p2+2 bne lb7 move4 sym,alpha alpha = sym bra lb8 return lb7 ldy #symAlpha p2^.symAlpha = sym lda sym sta [p2],Y iny iny lda sym+2 sta [p2],Y lb8 ret ; ; Local data ; lens ds 2 shortest string length len1 ds 2 length(sym^.symName) len2 ds 2 length(p1^.symName) end **************************************************************** * * CreateSymbol - create a new symbol table entry * * Inputs: * name - name of the new entry * hashDisp - disp in hash table for the entry * * Outputs: * returns a pointer to the new symbol table entry * **************************************************************** * CreateSymbol private using Common using OutCommon using SymbolCommon entryLength equ 1 length of the symbol table entry sym equ 3 ptr to symbol table entry p1 equ 7 work pointer sub (4:name),10 lda [name] no match - create a symbol table entry and #$00FF sec adc #symSize sta entryLength cmp poolSize ble cs2 jsr AllocatePool no room - get a new pool cs2 sub2 poolSize,entryLength subtract the space we need clc update the pool pointer and get a copy lda poolPtr sta sym adc entryLength sta poolPtr lda poolPtr+2 sta sym+2 adc #0 sta poolPtr+2 ldx hashDisp place the record in the hash list ldy #2 lda table,X sta [sym] lda table+2,X sta [sym],Y lda sym sta table,X lda sym+2 sta table+2,X ldy #symSeg record our load segment number lda loadNumber sta [sym],Y ldy #symFile record our file number lda fileNumber sta [sym],Y ldy #symFlag the value is not resolved lda #0 sta [sym],Y ldy #symPriv the symbol is not private sta [sym],Y add4 sym,#symName,p1 record the symbol name lda [name] and #$00FF tay short M cs3 lda [name],Y sta [p1],Y dey bpl cs3 long M lda symbols if the symbol table will be printed then beq cs4 ph4 sym insert in alphabetical list jsr AlphaInsert cs4 ret 4:sym end **************************************************************** * * Define - define a symbol * * Inputs: * name - ptr to the symbol name * length - length attribute * type - type attribute * private - is the symbol private? * global - is the symbol global? (or local) * expression - is the value an expression? (or a constant) * value - symbol value, or pointer to the expression * isData - is the symbol a data area name? * isSegment - is the symbol a segment name? * **************************************************************** * Define start using Common using SymbolCommon using ExpCommon using OutCommon sym equ 1 pointer to symbol table entry sub (4:name,2:length,2:type,2:private,2:global,2:expression,4:value,2:isData,2:isSegment),4 lda global if the symbol is local then bne fs1 lda dataNumber if dataNumber = 0 then jeq lb2 return {don't define the symbol!} ! {get a symbol to define} fs1 ph4 name if ((sym = FindSymbol(name)) != NULL) { jsr FindSymbol sta sym stx sym+2 ora sym+2 beq fs5 ldy #symFile if (sym->symFile == fileNumber) lda [sym],Y cmp fileNumber beq fs6 goto fs6; fs2 ldy #symFile while (sym->symFile != fileNumber) { lda [sym],Y cmp fileNumber beq fs4 fs3 ldy #2 sym = sym->symNext; lda [sym] tax lda [sym],Y sta sym+2 stx sym ora sym if (sym == NULL) beq fs5 goto fs5; bra fs2 } fs4 clc if (!Match(& sym->symName,name)) { lda sym adc #symName tax lda sym+2 adc #^symName pha phx ph4 name jsr Match tax beq fs6 bra fs3 sym = sym->symNext; ! if (sym == NULL) ! goto fs5; ! goto fs2; ! } ! } bra fs6 else fs5 ph4 name sym = CreateSymbol(name); jsr CreateSymbol sta sym stx sym+2 fs6 anop lda expression if the value is an expression then beq ex1 ph4 value copy the expression jsr CopyExpression ldy #symVal sta [sym],Y ldy #symVal+2 txa sta [sym],Y ldy #symExp set the expression flag lda copiedExpression sta [sym],Y bne ex2 if a constant was returned then ldy #symFlag set the constant flag lda #isConstant ora [sym],Y sta [sym],Y bra ex2 else ex1 ldy #symVal save the symbol value lda value sta [sym],Y ldy #symVal+2 lda value+2 sta [sym],Y ldy #symExp clear expression flag lda #0 sta [sym],Y ex2 anop endif ldy #symLength set the length attribute lda length sta [sym],Y ldy #symType set the type attribute lda type sta [sym],Y ldy #symPriv set the private flag lda private sta [sym],Y ldy #symData set the data area number lda dataNumber ldx global beq ex3 ldx isData bne ex3 lda #0 ex3 sta [sym],Y ldy #symFile set the file number lda fileNumber sta [sym],Y ldy #symSeg set the load segment number lda loadNumber sta [sym],Y ldy #symFlag set the "resolved on pass 1" flag lda [sym],Y ora #pass1Resolved+pass1Requested sta [sym],Y lda isData if isData then beq lb2 ! ldy #symFlag set the data area flag lda [sym],Y ora #isDataArea sta [sym],Y lb2 lda isSegment if isSegment then beq lb3 ! ldy #symFlag set the segment flag lda [sym],Y ora #isSegmentFlag sta [sym],Y lb3 ret end **************************************************************** * * Define2 - note that the symbol is resolved on pass 2 * * Inputs: * name - ptr to the symbol name * global - is the symbol global? * value - value, or 0 if the value does not need to be checked * **************************************************************** * Define2 start using Common using SymbolCommon sym equ 1 pointer to symbol table entry p1 equ 5 copy of sym; used for duplicate check sub (4:name,2:global,4:value),8 lda global if the symbol is local then bne lb1 lda dataNumber if dataNumber = 0 then jeq lb10 return {don't define the symbol!} ! /* find the correct symbol */ lb1 ph4 name sym = FindSymbol(name); jsr FindSymbol p1 = sym; sta sym sta p1 stx sym+2 stx p1+2 ldy #symFile if (sym->symFile != fileNumber) { lda [sym],Y cmp fileNumber beq lb5 lb2 ldy #symFile while (sym->symFile != fileNumber) lda [sym],Y cmp fileNumber beq lb4 lb3 ldy #2 sym = sym->symNext; lda [sym],Y tax lda [sym] sta sym stx sym+2 bra lb2 lb4 clc if (!Match(& sym->symName,name) { lda sym adc #symName tax lda sym+2 adc #^symName pha phx ph4 name jsr Match tax bne lb3 ! sym = sym->symNext; ! goto lb2; ! } ! } ! /* check for duplicates in this file */ lb5 ldy #symFlag if (sym->symFlag & pass2Resolved) lda [sym],Y and #pass2Resolved bne lb7 ! Error(DUPLICATE_SYMBOL); ! /* check for duplicate globals in */ ! /* two different files */ ldy #symPriv else if ((global) && (!sym^.symPriv)){ lda [sym],Y bne lb9 lb6 lda p1 while (p1 != NULL) { ora p1+2 beq lb9 cmpl p1,sym if (p1 != sym) beq lb8 clc if (Match(p1->symName,name)) lda p1 adc #symName tax lda p1+2 adc #^symName pha phx ph4 name jsr Match tax bne lb8 ldy #symPriv if (!p1->symPriv) { lda [p1],Y bne lb8 ldy #symFlag if (p1->symFlag & pass2Resolved) lda [p1],Y and #pass2Resolved beq lb8 lb7 ph4 name Error(DUPLICATE_SYMBOL); ph2 #1 jsr Error bra lb9 goto lb9; ! } lb8 ldy #2 p1 = p1->symNext; lda [p1],Y tax lda [p1] sta p1 stx p1+2 bra lb6 } ! } lb9 anop ldy #symFlag set the "resolved on pass 2" flag lda [sym],Y ora #pass2Resolved+pass2Requested sta [sym],Y ldy #symExp if the symbol is an expression then lda [sym],Y beq lb9a ldy #symVal+2 make sure all needed symbols are lda [sym],Y available ; and #$FF00 debug ; beq db1 debug ; brk $33 debug ;b1 lda [sym],Y debug pha dey dey lda [sym],Y pha jsr Evaluate lb9a lda value if value <> 0 then ora value+2 beq lb10 ldy #symVal if value <> sym^.symVal then lda [sym],Y cmp value bne lb9b iny iny lda [sym],Y cmp value+2 beq lb10 lb9b ph4 name addressing error ph2 #7 jsr Error lb10 ret end **************************************************************** * * FindFirstSymbol - find the alphabetically smallest symbol * * Inputs: * r12 - head of the symbol table * * Outputs: * r0 - pointer to the first symbol * r12 - pointer to the remaining symbols * C - set if a symbol was found, else clear * * Notes: * Only symbols resolved on pass 2 are returned. * **************************************************************** * FindFirstSymbol private using Common using SymbolCommon lb0 lda r12 if r12 = nil then ora r14 bne lb1 return false clc rts lb1 move4 r12,r0 r0 = r12 ldy #symAlpha r12 = r0^.symAlpha lda [r0],Y sta r12 iny iny lda [r0],Y sta r14 ldy #symFlag if the symbol was not resolved then lda [r0],Y and #pass2Resolved beq lb0 skip this one sec return true rts end **************************************************************** * * FindSymbol - find a symbol * * Inputs: * name - pointer to the symbol name * * Outputs: * A-X - address of the symbol table entry; nil for none * hashDisp - hash table displacement * * Notes: * There may be several symbols with the same name. In * that case, this subroutine returns the first one in * the hash bucked. You can scan forward from sym^.next * to find the others. * **************************************************************** * FindSymbol private using SymbolCommon sym equ 1 symbol table pointer sub (4:name),4 ph4 name get the address of the proper hash bucket jsr Hash sta hashDisp tax lda table,X sta sym lda table+2,X sta sym+2 ora sym branch if it is empty beq lb2 lb1 clc if the names match then lda sym adc #symName tax lda sym+2 adc #0 pha phx ph4 name jsr Match tax beq lb2 return ldy #2 next symbol lda [sym],Y tax lda [sym] sta sym stx sym+2 ora sym+2 bne lb1 lb2 ret 4:sym end **************************************************************** * * GetSymbolMemory - get memory from the symbol table pool * * Inputs: * size - number of bytes to reserve * * Outputs: * returns a pointer to the memory * **************************************************************** * GetSymbolMemory start using SymbolCommon ptr equ 1 pointer to the memory sub (2:size),4 lda size if there isn't enough room then cmp poolSize ble lb2 cmp #blockSize if the request is bigger than blt lb1 blockSize then pea 0 get the memory from MLalloc pha jsr MLAlloc sta ptr stx ptr+2 bra lb3 return lb1 jsr AllocatePool no room - get a new pool lb2 sub2 poolSize,size subtract the space we need clc update the pool pointer and get a copy lda poolPtr sta ptr adc size sta poolPtr lda poolPtr+2 sta ptr+2 adc #0 sta poolPtr+2 lb3 ret 4:ptr end **************************************************************** * * GetSymbolValue - get the value of a symbol; for Evaluate only! * * Inputs: * name - name of the symbol * strong - strong reference? (or weak) * fileNumber - current file number * expSegment - segment for the current expression * * Outputs: * symbolValue - symbol value * symbolRelocatable - is the symbol relocatable? * symbolLength - length attribute * symbolCount - count attribute * symbolType - type attribute * symbolFlag - symbol flags * symbolData - data area number * **************************************************************** * GetSymbolValue start using Common using OutCommon using SymbolCommon using ExpCommon sym equ 1 pointer to the symbol p1 equ 5 work pointer sub (4:name,2:strong),8 ; ; Find the symbol in the hash table ; ph4 name find the symbol jsr FindSymbol sta sym sta p1 stx sym+2 stx p1+2 ora p1+2 beq nosym ; ; Find the private version of the symbol. Use it if it is resolved. ; ldy #symFile if p1^.symFile <> fileNumber then lda [p1],Y cmp fileNumber beq lb4 lb1 ldy #symFile while p1^.symFile <> fileNumber do lda [p1],Y cmp fileNumber beq lb3 lb2 ldy #2 p1 := p1^.next; lda [p1],Y tax lda [p1] sta p1 stx p1+2 ora p1+2 beq gb1 bra lb1 lb3 clc if not Match(p1^.symName,name) then lda #symName adc p1 tax lda #^symName adc p1+2 pha phx ph4 name jsr Match tax bne lb2 p1 := p1^.next; ! goto 1; ! endif lb4 anop endif ldy #symFlag if the private symbol is resolved then lda [p1],Y and #pass1Resolved beq gb1 move4 p1,sym use it bra sv1 ; ; Find the global version of the symbol. ; gb1 ldy #symFlag while not (sym^.symFlag & pass1Resolved) do lda [sym],Y and #pass1Resolved bne gb3 gb2 ldy #2 sym := sym^.next; lda [sym],Y tax lda [sym] sta sym stx sym+2 ora sym+2 if sym = nil then bne gb1 nosym stz symbolValue symbolValue = 0 stz symbolValue+2 stz symbolRelocatable symbolRelocatable = false stz symbolLength symbolLength = 0 stz symbolCount symbolCount = 0 stz symbolType symbolType = 0 stz symbolFlag symbolFlag = 0 stz symbolData symbolData = 0 stz symbolFile symbolFile = 0 lda strong if the reference is strong then jeq rt1 ph4 name flag the error ph2 #6 jsr Error brl rt1 return gb3 ldy #symPriv if sym^.symPriv then lda [sym],Y bne gb2 sym := sym^.next; ! goto 1; ! endif clc if not Match(sym^.symName,name) then lda #symName adc sym tax lda #^symName adc sym+2 pha phx ph4 name jsr Match tax bne gb2 sym := sym^.next; ! goto 1; ! endif ! endif ; ; Set the symbol values ; sv1 ldy #symExp if the value is an expression then lda [sym],Y jeq sv2 ph2 copiedExpression save volitile variables ph4 shiftCount ph2 shiftFlag ph4 shiftValue ph2 symbolCount ph2 symbolLength ph2 symbolRelocatable ph2 symbolType ph4 symbolValue ldy #symVal+2 evaluate the expression lda [sym],Y pha dey dey lda [sym],Y pha jsr Evaluate sta symbolValue save the value stx symbolValue+2 lda shiftFlag if the value is shifted then beq sv1a ph4 name flag the error ph2 #2 jsr Error sv1a lda symbolRelocatable if the symbol is relocatable then beq sv1c jsr CheckSegment check for errors ldy #symSeg set the expression file lda [sym],Y sta expSegment sv1c pl4 symbolValue restore volitile variables pl2 symbolType pl2 symbolRelocatable pl2 symbolLength pl2 symbolCount pl4 shiftValue pl2 shiftFlag pl4 shiftCount pl2 copiedExpression bra sv3 else sv2 ldy #symVal set the value lda [sym],Y sta symbolValue iny iny lda [sym],Y sta symbolValue+2 stz symbolRelocatable set the relocation flag ldy #symFlag lda [sym],Y and #isConstant bne sv3 inc symbolRelocatable if relocatable then jsr CheckSegment check for cross-file errors ldy #symSeg set the expression file lda [sym],Y sta expSegment sv3 anop endif lda #1 count attribute is 1 sta symbolCount ldy #symLength set the length attribute lda [sym],Y sta symbolLength ldy #symType set the type attribute lda [sym],Y sta symbolType ldy #symFlag set the flags lda [sym],Y sta symbolFlag ldy #symFile set the file lda [sym],Y sta symbolFile ldy #symData set the data area number lda [sym],Y sta symbolData beq rt1 if symbolData <> 0 then lda symbolFlag if not symbolFlag & isDataArea then and #isDataArea bne rt1 ldx symbolData if not dataAreas[symbolData] then lda dataAreas,X and #$00FF bne rt1 lda strong if the reference is strong then beq rt1 ph4 name flag unresolved reference ph2 #6 jsr Error rt1 ret ; ; CheckSegment - check for cross-file expressions ; CheckSegment anop lda expSegment if the expression is file-sensitive beq cf1 then ldy #symSeg verify that the files match cmp [sym],Y beq cf1 clc nope -> flag the error lda sym adc #symName tax lda sym+2 adc #^symName pha phx ph2 #24 jsr Error cf1 rts end **************************************************************** * * Hash - find the hash tabe displacement for a symbol * * Inputs: * ptr - pointer to the symbol name * * Outputs: * returns the displacement into table * **************************************************************** * Hash private using SymbolCommon disp equ 1 hash displacement temp equ 3 temp value; for forming char pairs sub (4:ptr),4 ! {get ready for the sum loop} lda [ptr] get the # of characters and #$00FF lsr A X = numChars div 2 tax bcc lb1 if odd(numChars) then lda [ptr] disp = ch[1] & $3F xba and #$003F sta disp ldy #2 Y = 2 bra lb2 else lb1 stz disp disp = 0 ldy #1 y = 1 lb2 anop endif ! {add pairs of characters to the sum} txa quit now if there was 1 character beq lb4 lb3 lda [ptr],Y fetch a character pair and #$003F compact it to 12 bits sta temp lda [ptr],Y and #$3F00 lsr A lsr A ora temp adc disp add the result to disp sta disp iny next pair iny dex bne lb3 ! {create a hash table displacement} lb4 lda disp mod result with # of buckets lb5 cmp #hashSize blt lb6 sec sbc #hashSize bra lb5 lb6 asl A convert to a displacement asl A sta disp ret 2:disp end **************************************************************** * * InitSymbol - initialize the symbol table module * * Outputs: * poolSize - set to 0 * table - all pointers set to nil * **************************************************************** * InitSymbol start using SymbolCommon stz alpha alpha = nil stz alpha+2 stz poolSize no bytes in the symbol pool move #0,table,#hashSize*4 zero the hash table rts end **************************************************************** * * Match - see if two names match * * Inputs: * p1,p2 - pointers to the two names * * Outputs: * A - 0 if the names match, 1 if they do not * * Notes: * This subroutine assumes that the names are not null * strings. * **************************************************************** * Match private res equ 1 do the names match? sub (4:p1,4:p2),2 lda #1 assume they do not match sta res lda [p1] check the length & first char cmp [p2] bne mt2 and #$00FF check the characters tay short M mt1 lda [p1],Y cmp [p2],Y bne mt2 dey bne mt1 long M stz res the strings match mt2 long M ret 2:res end **************************************************************** * * NeedSegment - do we need this symbol from the library? * * Inputs: * name - pointer to the symbol name * priv - private flag * fileNumber - symbol's file number * pass - pass number * * Outputs: * A - 1 if we need it, 0 if we don't * **************************************************************** * NeedSegment start using Common using SymbolCommon need equ 1 do we need it? sp equ 3 symbol pointer maybe equ 7 we may need this symbol sub (4:name,2:priv),8 stz need assume we don't need it stz maybe so far, we have no need ph4 name if the symbol is not found then jsr FindSymbol sta sp stx sp+2 ora sp+2 jeq lb10 we don't need it lda priv if the library symbol is private then beq lb4 ldy #symFile if (sp->symFile != fileNumber) { lda [sp],Y cmp fileNumber beq lb3 lb1 ldy #symFile while (sp->symFile != fileNumber) { lda [sp],Y cmp fileNumber beq lb2a lb2 ldy #2 sp = sp->symNext; lda [sp],Y tax lda [sp] sta sp stx sp+2 ora sp+2 if (sp == NULL) jeq lb10 return false; bra lb1 } lb2a clc if (!Match(sp->symName,sp)) { lda sp adc #symName tax lda sp+2 adc #^symName pha phx ph4 name jsr Match tax bne lb2 ! sp = sp->symNext; ! goto lb1; lb3 anop } jsr CheckSymbol check the symbol bcc lb10 inc need bra lb10 lb4 anop else {if library symbol is global then} lda sp while (sp != NULL) ora sp+2 beq lb7 ldy #symPriv if (!sp->symPriv) lda [sp],Y bne lb6 clc if (Match(sp->symName,name)) lda sp adc #symName tax lda sp+2 adc #^symName pha phx ph4 name jsr Match tax bne lb6 lda pass if the symbol is resolved then cmp #1 bne lb5 lda #pass1Resolved bra lb5a lb5 lda #pass2Resolved lb5a ldy #symFlag and [sp],Y bne lb10 we don't need this segment lda pass if the symbol is requested then cmp #1 bne lb5b lda #pass1Requested bra lb5c lb5b lda #pass2Requested lb5c ldy #symFlag and [sp],Y beq lb6 inc maybe we may need this segment lb6 ldy #2 sp = sp->symNext; lda [sp],Y tax lda [sp] sta sp stx sp+2 bra lb4 lb7 lda maybe if maybe then beq lb10 inc need we need this symbol lb10 ret 2:need ; ; Check the symbol ; CheckSymbol anop lda pass if (pass == 1) { cmp #1 bne cs1 ldy #symFlag if (sp->symFlag & pass1Requested) lda [sp],Y bit #pass1Requested beq cs2 bit #pass1Resolved if (!(sp->symFlag & pass1Resolved) bne cs2 sec return true; rts ! } ! else {pass == 2} cs1 ldy #symFlag if (sp->symFlag & pass2Requested) lda [sp],Y bit #pass2Requested beq cs2 bit #pass2Resolved if (!(sp->symFlag & pass2Resolved) bne cs2 sec return true; rts ! } cs2 clc return false rts end **************************************************************** * * PrintSymbol - print one symbol * * Inputs: * r0 - pointer to the symbol table entry * **************************************************************** * PrintSymbol private using Common using SymbolCommon ldy #symVal+2 push the symbol value lda [r0],Y pha dey dey lda [r0],Y pha ldy #symExp if the symbol is an expression then lda [r0],Y beq lb0 jsr Evaluate evaluate the expression phx pha lb0 ph2 #8 print the symbol value ph2 #0 jsr PrintHex ldy #symPriv print the global/private flag lda [r0],Y beq lb1 puts #' P ' bra lb2 lb1 puts #' G ' lb2 ldy #symSeg print the load segment number lda [r0],Y ldx kflag beq lb3 ldx express beq lb3 inc A lb3 pea 0 pha ph2 #2 ph2 #0 jsr PrintHex putc #' ' ldy #symData print the data area number lda [r0],Y pea 0 pha ph2 #2 ph2 #0 jsr PrintHex putc #' ' add4 r0,#symName-1,r4 print the symbol name puts [r4] rts end **************************************************************** * * PrintSymbols - print the symbol table * * Inputs: * symbols - print symbols flag * **************************************************************** * PrintSymbols start using SymbolCommon using Common ; ; Write the header ; lda symbols quit if the symbol flag is off bne lb1 rts lb1 lda list write the header bne lb2 putcr putcr lb2 puts #'Global symbol table:',cr=t putcr ; ; Initialize the symbol list pointer ; move4 alpha,r12 ; ; Print the symbols ; stz col2 not doing column 2 ps1 jsr FindFirstSymbol find the next symbol to print bcc ps5 jsr PrintSymbol print it lda col2 if this one is in column 1 then bne ps4 inc col2 col2 = true ldy #symName get the length of the name lda [r0],Y and #$00FF sta r4 sec print the proper number of spaces lda #27 sbc r4 sta r4 beq ps2 bpl ps3 ps2 lda #1 sta r4 ps3 putc #' ' dec r4 bne ps3 bra ps1 else ps4 stz col2 col2 = false putcr write a CR jsr CheckForPause check for early exit bra ps1 next symbol ps5 lda col2 if in column 1 then bne ps6 putcr write the CR ps6 putcr lda list beq ps7 putcr putcr ps7 rts ; ; Local data ; col2 ds 2 end **************************************************************** * * Reference - make a reference to a symbol * * Inputs: * sp - pointer to the symbol name to reference * **************************************************************** * Reference start using Common using SymbolCommon ! {get a symbol to define} fs1 ph4 sp if ((r0 = FindSymbol(sp)) != NULL) { jsr FindSymbol sta r0 stx r0+2 ora r0+2 beq fs5 ldy #symFile if (r0->symFile == fileNumber) lda [r0],Y cmp fileNumber beq fs6 goto fs6; fs2 ldy #symFile while (r0->symFile != fileNumber) { lda [r0],Y cmp fileNumber beq fs4 fs3 ldy #2 r0 = r0->symNext; lda [r0] tax lda [r0],Y sta r2 stx r0 ora r0 if (r0 == NULL) beq fs5 goto fs5; bra fs2 } fs4 clc if (!Match(r0->symName,sp)) { lda r0 adc #symName tax lda r2 adc #^symName pha phx ph4 sp jsr Match tax bne fs3 rts r0 = r0->symNext; ! if (r0 == NULL) ! goto fs5; ! goto fs2; ! } ! } ! else fs5 ph4 sp CreateSymbol(sp); jsr CreateSymbol sta r0 stx r2 fs6 ldy #symFlag set the pass 1 requested flag lda [r0],Y ora #pass1Requested sta [r0],Y rts end **************************************************************** * * Reference2 - note that pass2 has requested a symbol * * Inputs: * sp - pointer to the symbol name to reference * **************************************************************** * Reference2 start using Common using SymbolCommon ph4 sp r0 = FindSymbol(sp); jsr FindSymbol sta r0 stx r2 ldy #symFile if (r0->symFile != fileNumber) { lda [r0],Y cmp fileNumber beq lb3 lb1 ldy #symFile while (r0->symFile != fileNumber) { lda [r0],Y cmp fileNumber beq lb2a lb2 ldy #2 r0 = r0->symNext; lda [r0],Y tax lda [r0] sta r0 stx r2 bra lb1 lb2a clc if (!Match(r0->symName,sp)) { lda r0 adc #symName tax lda r2 adc #^symName pha phx ph4 sp jsr Match tax bne lb2 ! r0 = r0->symNext; ! goto lb1; lb3 anop } ldy #symFlag set the pass 2 requested flag lda [r0],Y ora #pass2Requested sta [r0],Y rts end **************************************************************** * * Unresolved - are there unresolved references? * * Inputs: * pass - pass number * * Outputs: * C - set if there are unresolved references, else clear * **************************************************************** * Unresolved start using SymbolCommon using Common lda pass if pass1 then cmp #1 bne lb1 lda #pass1Resolved resolved = pass1Resolved ldx #pass1Requested requested = pass1Requested bra lb2 else lb1 lda #pass2Resolved resolved = pass2Resolved ldx #pass2Requested requested = pass2Requested lb2 sta resolved endif stx requested la index,hashSize*4-4 for each hash bucket do lb3 ldx index for each symbol in the bucket do lda table,X sta r0 sta r4 lda table+2,X sta r2 sta r6 ora r2 beq lb7 lb4 ldy #symFlag if r0^.symFlag & requested then lda [r0],Y bit requested beq lb6 bit resolved if not (r0^.symFlag & resolved) then bne lb6 ldy #symPriv if r0^.symPriv then lda [r0] beq lb5 jsr GlobalExists if GlobalExists then bcs lb6 skip request lb5 sec return true rts lb6 ldy #2 r0 = r0^.symNext lda [r0],Y tax lda [r0] sta r0 stx r2 ora r2 next symbol in bucket bne lb4 lb7 sec next bucket lda index sbc #4 sta index bpl lb3 clc no symbols needed rts ; ; GlobalExists - see if a global symbol by the name of r0^.symName exists ; GlobalExists anop move4 r4,r8 r8 = first sym in bucket add4 r0,#symName,r12 r12 = @r0^.symName ge1 ldy #symPriv for each symbol do lda [r8],Y if the symbol is global then bne ge2 clc if Match(r8^.symName,r12) then lda r8 adc #symName tax lda r10 adc #^symName pha phx ph4 r12 jsr Match tax bne ge2 sec return true rts ge2 ldy #2 next symbol lda [r8],Y tax lda [r8] sta r8 stx r10 ora r10 bne ge1 clc return false rts ; ; Local data ; index ds 2 index into the hash table resolved ds 2 resolved mask for this pass requested ds 2 requested mask for this pass end