*************************** * Dictionary Operations * *************************** dictbeg equ 0 dictpos equ 4 dictlim equ 8 dictalt equ 12 ************************************************** * Define name (D0=size,A0=name,A1=dict/D0=tag) * * D0<0: Name already defined D0=0: dict full * ************************************************** defname addq.l #3,d0 * Round up to an integral lsr.l #2,d0 * number of longwords movem.l d0-d2/a0-a3,-(sp) clr.l d0 move.b (a0)+,d0 * Length of string move.l dictbeg(a1),a2 cmp.l dictpos(a1),a2 bne.s dn1 * Dictionary not empty -> clr.l (a2)+ * Initialise dictionary clr.l (a2)+ move.l a2,dictpos(a1) subq.l #8,a2 dn1 clr.b d1 subq.l #1,d0 * Advance along string bmi.s dn2 * End of string: match 0 move.b (a0)+,d1 * Otherwise match next char dn2 move.l a2,a3 * A3 -> predecessor addq.l #4,a2 * A2 -> next candidate dn3 cmp.b (a2),d1 bne.s dn4 * Mismatch -> tst.b d1 bne dn1 * Not yet done -> move.l #$80000004,d0 * (Duplicate) add.l a2,d0 addq.l #4,sp movem.l (sp)+,d1/d2/a0-a3 rts dn4 clr.l d2 move.w 2(a2),d2 * get alt pointer beq.s dn5 * no alt -> lsl.l #2,d2 * scale-up add.l d2,a2 bra dn3 * Try alt dn5 move.l a3,d2 * Remember predecessor move.l dictpos(a1),a3 move.l d0,-(sp) * Preserve (rest of) string length addq.l #3,d0 * Test for dict overflow add.l 4(sp),d0 lsl.l #2,d0 add.l a3,d0 cmp.l dictlim(a1),d0 bge.s dn9 * Dict full -> move.l d0,dictpos(a1) * Allocate space move.l (sp)+,d0 sub.l a3,d2 clr.w (a3)+ neg.l d2 lsr.l #2,d2 * scale-down (back-pointer) move.w d2,(a3)+ move.l a3,d2 sub.l a2,d2 lsr.l #2,d2 * scale-down (alt-pointer) move.w d2,2(a2) dn6 move.b d1,(a3)+ clr.b (a3)+ clr.w (a3)+ tst.w d0 bmi.s dn7 * done -> clr.w d1 * Extract next char (or 0) subq.w #1,d0 bmi dn6 move.b (a0)+,d1 bra dn6 dn7 move.l a3,d0 addq.l #4,sp movem.l (sp)+,d1/d2/a0-a3 rts dn9 sub.l a3,a3 * Dictionary full addq.l #4,sp *30/05/85 bugfix bra dn7 ********************************************* * Reference name (A0=name,A1=dict/D0=tag) * * D0=0: not found, D0<0: approx match * ********************************************* refname movem.l d1/d2/a0-a2,-(sp) rn0 clr.l d0 move.b (a0)+,d0 * Length of string move.l dictbeg(a1),a2 rn1 clr.b d1 * Advance along string subq.l #1,d0 bmi.s rn2 * D1=0 for end of string -> move.b (a0)+,d1 rn2 addq.l #4,a2 * Advance along dict rn3 cmp.l dictpos(a1),a2 bge.s rn5 * Off end -> cmp.b (a2),d1 bne.s rn4 * Mismatch here -> tst.b d1 beq.s rn9 * Complete match -> bra rn1 rn4 clr.l d2 move.w 2(a2),d2 beq.s rn5 * No alt -> lsl.l #2,d2 * scale-up add.l d2,a2 bra rn3 * Try elsewhere rn5 tst.b d1 beq rn8 * Approx match -> move.l 8(sp),a0 * Reset string pointer move.l dictalt(a1),d0 * Try alt dict if any move.l d0,a1 bne rn0 clr.l d0 * Name not found => bra.s rn10 rn8 addq.l #4,a2 * scan to end of this name tst.b (a2) bne rn8 add.l #$80000000,a2 * (A2 preserved across recursive call) move.l 8(sp),a0 * Try alt dict for better match move.l dictalt(a1),d0 move.l d0,a1 beq.s rn9 * No alt dict -> bsr refname tst.l d0 bgt.s rn10 * Better match found -> rn9 addq.l #4,a2 move.l a2,d0 rn10 movem.l (sp)+,d1/d2/a0-a2 rts ************************************* * Translate name (D0=tag,A0=name) * ************************************* transname movem.l d0-d2/a0-a2,-(sp) clr.b (a0) * string = "" lea 1(a0),a1 * Pointer along string move.l d0,a2 * Dict tag subq.l #8,a2 * Pointer along dict tn1 move.b (a2),d0 * Character bne.s tn2 * Genuine -> clr.l d0 move.w 2(a2),d0 * Get predecessor beq.s tn3 * None -> lsl.l #2,d0 * scale-up sub.l d0,a2 bra tn1 tn2 move.b d0,(a1)+ subq.l #4,a2 * Get predecessor bra tn1 tn3 move.l a1,d0 sub.l a0,d0 subq.b #1,d0 move.b d0,(a0) * Set string length lea 1(a0),a2 tn4 subq.b #2,d0 * Reverse the string bmi.s tn5 * Done -> move.b (a2),d1 move.b -(a1),d2 move.b d1,(a1) move.b d2,(a2)+ bra tn4 tn5 movem.l (sp)+,d0-d2/a0-a2 rts end