; SwatSymA.asm -- Companion to SwatSymB.bcpl
; Copyright Xerox Corporation 1982
; Last modified March 23, 1982  6:17 PM by Boggs

; outgoing procedures
.ent ScanSymBuffer
.ent FindSym, ClosestPL, ClosestV

; incoming statics
.bext p, s, a

	.srel

ScanSymBuffer: .ScanSymBuffer
FindSym: .FindSym
ClosestPL: .ClosestPL
ClosestV: .ClosestV

	.nrel

; ScanSymBuffer(ptr, endPtr, name)
; Scans memory in the region [ptr..endPtr) looking at symbols,
;  and returns a pointer to a symbol that either matches name or
;  extends to or beyond endPtr.


name = 0
thisPtr = 1
frame = 2
endPtr = 3
nextPtr = 4
tempName = 5
tempLength = 6

; Equivalent BCPL code:
; and ScanSymBuffer(ptr, endPtr, symbol) = valof
; [
; let len = ptr>>String.length rshift 1 +1
; if ptr+len uge endPtr resultis ptr
; if StringCompare(ptr, symbol) eq 0 resultis ptr
; ptr = ptr + len
; ] repeat

.ScanSymBuffer:
	sta 3 1,2
	jsr ssb			; ac3 -> table
	.blk 7
ssb:	sta 0 nextPtr,3		; save ptr
	sta 1 endPtr,3		; save endPtr
	sta 2 frame,3		; save frame
	lda 0 3,2
	sta 0 name,3		; save name

; Examine next symbol -- compute length
nextSym:lda 2 nextPtr,3		; get ptr to symbol
	sta 2 thisPtr,3
	lda 0 0,2
	lda 1 c177400
	ands 1 0		; thisPtr>>String.length
	movzr 0 0		; rshift 1
	inc 0 0			; +1
	sta 0 tempLength,3	; length in words

; Check for symbol extending beyond end of buffer
	add 2 0			; ac0← ptr+length
	sta 0 nextPtr,3		; pointer to next symbol
	lda 1 endPtr,3		; endPtr
	sltu 0 1
	 jmp exit		; extends to or beyond end, exit

; Compare first word of symbol (length and first character).
; Most mismatches should occur at this point.
	lda 0 0,2		; get word from symbol
	lda 1 c177737		; capitalize first character
	and 1 0
	lda 1 @name,3		; get word from name
	se 1 0
	 jmp nextSym		; did not match, advance to next symbol

; First word matched.  Now prepare to check the rest of the name.
	lda 1 c177400
	ands 1 0		; # of characters in symbol
	movzr 0 0 szc		; if even then must handle garbage byte
	 jmp scomp		; odd
	add 2 0			; ac0 is address of last word of symbol
	sta 0 tempName,3	; (out of index registers)
	lda 0 @tempName,3	; pick up last word
	and 1 0			; set low (garbage) byte to zero
	sta 0 @tempName,3	; put it back
scomp:	lda 0 name,3		; set up name pointer and length in temps
	sta 0 tempName,3
	jmp ecomp

; Symbol/Name compare loop
comp:	inc 2 2			; advance symbol pointer
	isz tempName,3		; advance name pointer
	lda 0 0,2		; get word from symbol
	lda 1 c157737		; capitalize letters
	and 1 0
	lda 1 @tempName,3	; get word from name
	se 1 0
	 jmp nextSym		; did not match, advance to next symbol
ecomp:	dsz tempLength,3	; decrement and test word count
	 jmp comp		; continue

; Here to exit.  ac3 -> ssb.
exit:	lda 0 thisPtr,3		; return ptr
	lda 2 frame,3		; recover frame
	lda 3 1,2
	jmp 1,3

c177737: 177737
c157737: 157737
c177400: 177400


; and FindSym(sym) be	//asm coded for speed
;    if sym>>Sym.builtIn eq 0 & sym>>Sym.inCache eq 0 &
;     sym>>Sym.namePos eq p then s = sym
.FindSym:
	sta 3 1,2
	mov 0 3		; sym
	lda 0 1,3	; flag word
	lda 1 c600	; flag mask
	and 1 0 szr	; either flag set?
	 jmp FSExit	; yes.
	lda 0 0,3	; sym.namePos
	lda 1 @.p	; p
	sne 0 1		; same?
	 sta 3 @.s	; s = sym
FSExit:	lda 3 1,2
	jmp 1,3

c600:	600
.p:	p
.s:	s

; and ClosestPL(sym) be	//asm coded for speed
;    if s>>Sym.value uls sym>>Sym.value & sym>>Sym.value ule a &
;     s>>Sym.bank eq sym>>Sym.bank then s = sym
.ClosestPL:
	sta 3 1,2
	mov 0 3		; sym
	sta 2 save2
	lda 2 @.s	; s
	lda 0 3,2	; s.value
	lda 1 3,3	; sym.value
	sltu 0 1
	 jmp PLExit
	lda 0 @.a	; a
	sleu 1 0
	 jmp PLExit
	lda 0 1,3	; sym.bank
	lda 1 1,2	; s.bank
	lda 2 c3
	and 2 0
	and 2 1
	sne 0 1
	 sta 3 @.s	; s = sym
PLExit:	lda 2 save2
	lda 3 1,2
	jmp 1,3

c3:	3
save2:	0
.a:	a

; and ClosestV(sym) be  //asm coded for speed
;   if sym>>Sym.addr eq a then s = sym

.ClosestV:
	sta 3 1,2
	mov 0 3		; sym
	lda 0 2,3	; sym.addr
	lda 1 @.a	; a
	sne 0 1
	 sta 3 @.s	; s = sym
	lda 3 1,2
	jmp 1,3

	.end