Refactor dictionary access:
- introduce WordListEntry type;
- introduce accessors and mutators for wordlist entries;
- hide some implementation details;
- prepare to hide more implementation details.

--- csrc/pf_guts.h	26 Aug 2010 10:25:09 -0000	1.1.1.7
+++ csrc/pf_guts.h	30 Nov 2010 19:44:44 -0000
@@ -57,11 +57,6 @@
 #define FTRUE (-1)
 #define BLANK (' ')
 
-#define FLAG_PRECEDENCE (0x80)
-#define FLAG_IMMEDIATE  (0x40)
-#define FLAG_SMUDGE     (0x20)
-#define MASK_NAME_SIZE  (0x1F)
-
 /* Debug TRACE flags */
 #define TRACE_INNER     (0x0002)
 #define TRACE_COMPILE   (0x0004)
@@ -409,12 +404,12 @@
 } pfNode;
 
 /* Structure of header entry in dictionary. These will be stored in dictionary specific endian format*/
-typedef struct cfNameLinks
+typedef struct WordListEntry
 {
-	cell_t       cfnl_PreviousName;   /* name relative address of previous */
-	ExecToken  cfnl_ExecToken;      /* Execution token for word. */
-/* Followed by variable length name field. */
-} cfNameLinks;
+	cell_t     next;   /* most recently defined ones first */
+	ExecToken  xt;     /* execution token */
+	char       name[]; /* variable length name */
+} WordListEntry;
 
 #define PF_DICF_ALLOCATED_SEGMENTS  ( 0x0001)
 typedef struct pfDictionary_s
--- csrc/pfcompil.c	22 Nov 2010 00:30:21 -0000	1.1.1.7
+++ csrc/pfcompil.c	30 Nov 2010 21:28:58 -0000
@@ -49,46 +49,77 @@
 	return -1;
 }
 
-#ifndef PF_NO_SHELL
-/***************************************************************
-** Create an entry in the Dictionary for the given ExecutionToken.
-** FName is name in Forth format.
-*/
-void CreateDicEntry( ExecToken XT, const ForthStringPtr FName, ucell_t Flags )
+/* Low-level details: */
+#define FLAG_PRECEDENCE (0x80)
+#define FLAG_IMMEDIATE  (0x40)
+#define FLAG_SMUDGE     (0x20)
+#define MASK_NAME_SIZE  (0x1F)
+
+/* WordListEntry accessors and mutators */
+ExecToken getAction(WordListEntry *wlp){return wlp->xt;}
+void setAction(WordListEntry *wlp, ExecToken xt){wlp->xt = xt;}
+
+void setFlags(WordListEntry *wlp, ucell_t flags){wlp->name[0] |= flags;}
+
+int isImmediate(WordListEntry *wlp){return !!(wlp->name[0] & FLAG_IMMEDIATE);}
+void setImmediate(WordListEntry *wlp){wlp->name[0] |= FLAG_IMMEDIATE;}
+void resetImmediate(WordListEntry *wlp){wlp->name[0] &= ~FLAG_IMMEDIATE;}
+
+int isSmudge(WordListEntry *wlp){return !!(wlp->name[0] & FLAG_SMUDGE);}
+void setSmudge(WordListEntry *wlp){wlp->name[0] |= FLAG_SMUDGE;}
+void resetSmudge(WordListEntry *wlp){wlp->name[0] &= ~FLAG_SMUDGE;}
+
+void getName(WordListEntry *wlp, cell_t *ptr, cell_t *len)
 {
-	cfNameLinks *cfnl;
+	*ptr = (cell_t)(wlp->name + 1);
+	*len = wlp->name[0] & MASK_NAME_SIZE;
+}
 
-	cfnl = (cfNameLinks *) gCurrentDictionary->dic_HeaderPtr;
+#ifndef PF_NO_SHELL
+/* Creating dictionary entry */
+WordListEntry *createEntry(const char *name, ucell_t namelen)
+{
+	WordListEntry *wle;
 
-/* Set link to previous header, if any. */
-	if( gVarContext )
-	{
-		WRITE_CELL_DIC( &cfnl->cfnl_PreviousName, ABS_TO_NAMEREL( gVarContext ) );
-	}
-	else
-	{
-		cfnl->cfnl_PreviousName = 0;
-	}
+	wle = (WordListEntry *) gCurrentDictionary->dic_HeaderPtr;
 
-/* Put Execution token in header. */
-	WRITE_CELL_DIC( &cfnl->cfnl_ExecToken, XT );
+	pfCopyMemory(wle->name + 1, name, namelen & MASK_NAME_SIZE);	/* Laydown name. */
+	wle->name[0] = namelen;
 
 /* Advance Header Dictionary Pointer */
-	gCurrentDictionary->dic_HeaderPtr += sizeof(cfNameLinks);
-
-/* Laydown name. */
-	gVarContext = gCurrentDictionary->dic_HeaderPtr;
-	pfCopyMemory( (uint8_t *) gCurrentDictionary->dic_HeaderPtr, FName, (*FName)+1 );
-	gCurrentDictionary->dic_HeaderPtr += (*FName)+1;
+	gCurrentDictionary->dic_HeaderPtr += sizeof(WordListEntry) + 1 + namelen;
 
-/* Set flags. */
-	*(char*)gVarContext |= (char) Flags;
-	
 /* Align to quad byte boundaries with zeroes. */
 	while( gCurrentDictionary->dic_HeaderPtr & UINT32_MASK )
 	{
 		*(char*)(gCurrentDictionary->dic_HeaderPtr++) = 0;
 	}
+
+	return wle;
+}
+
+void addEntry(cell_t *wl, WordListEntry *wle)
+{
+	/* Set link to previous header, if any. */
+	if (*wl) {
+		WRITE_CELL_DIC(&wle->next, ABS_TO_NAMEREL(*wl));
+	} else
+		wle->next = 0;
+	*wl = (cell_t)wle->name;	/* Link. */
+}
+
+/***************************************************************
+** Create an entry in the Dictionary for the given ExecutionToken.
+** FName is name in Forth format.
+*/
+void CreateDicEntry( ExecToken XT, const ForthStringPtr name, ucell_t Flags )
+{
+	WordListEntry *wle;
+
+	wle = createEntry (name+1, *(unsigned char*)name);
+	setAction (wle, XT);		/* Put Execution token in header. */
+	setFlags (wle, Flags);		/* Set flags. */
+	addEntry (&gVarContext, wle);
 }
 
 /***************************************************************
@@ -101,6 +132,29 @@
 	CreateDicEntry( XT, FName, Flags );
 }
 
+ForthString *tonfa(void *ptr)
+{
+	return ((WordListEntry *)ptr)->name;
+}
+
+WordListEntry *fromnfa(void *ptr)
+{
+	if (ptr == NULL) return NULL;
+	else return (WordListEntry *)((char *)ptr - sizeof(WordListEntry));
+}
+
+WordListEntry *NextEntry(WordListEntry *wle)
+{
+	cell_t relptr;
+
+	relptr = READ_CELL_DIC(&wle->next);
+	if (relptr) {
+		return fromnfa((char *)NAMEREL_TO_ABS(relptr));
+	} else {
+		return NULL;
+	}
+}
+
 /***************************************************************
 ** Convert absolute namefield address to previous absolute name
 ** field address or NULL.
@@ -108,12 +162,12 @@
 const ForthString *NameToPrevious( const ForthString *NFA )
 {
 	cell_t RelNamePtr;
-	const cfNameLinks *cfnl;
+	const WordListEntry *cfnl;
 
 /* DBUG(("\nNameToPrevious: NFA = 0x%x\n", (cell_t) NFA)); */
-	cfnl = (const cfNameLinks *) ( ((const char *) NFA) - sizeof(cfNameLinks) );
+	cfnl = (const WordListEntry *) ( ((const char *) NFA) - sizeof(WordListEntry) );
 
-	RelNamePtr = READ_CELL_DIC((const cell_t *) (&cfnl->cfnl_PreviousName));
+	RelNamePtr = READ_CELL_DIC((const cell_t *) (&cfnl->next));
 /* DBUG(("\nNameToPrevious: RelNamePtr = 0x%x\n", (cell_t) RelNamePtr )); */
 	if( RelNamePtr )
 	{
@@ -129,12 +183,12 @@
 */
 ExecToken NameToToken( const ForthString *NFA )
 {
-	const cfNameLinks *cfnl;
+	const WordListEntry *wle;
 
 /* Convert absolute namefield address to absolute link field address. */
-	cfnl = (const cfNameLinks *) ( ((const char *) NFA) - sizeof(cfNameLinks) );
+	wle = (const WordListEntry *) (((const char *) NFA) - sizeof(WordListEntry));
 
-	return READ_CELL_DIC((const cell_t *) (&cfnl->cfnl_ExecToken));
+	return READ_CELL_DIC((const cell_t *) (&wle->xt));
 }
 
 /***************************************************************
@@ -436,51 +490,54 @@
 	return Result;
 }
 
+WordListEntry *ffFindEntry(const char *word, ucell_t wordlen)
+{
+	const char *name;
+	cell_t namelen;
+	WordListEntry *wlp;
+
+DBUG(("\nffFindEntry: WordLen = %d, WordName = %*s\n", wordlen, wordlen, word));
+DBUG(("\nffFindEntry: Context = 0x%x\n", gVarContext));
+
+	/* Traverse linked list: */
+	for (wlp = fromnfa((char *)(gVarContext));
+	     wlp != NULL;
+	     wlp = NextEntry(wlp))
+	{
+		namelen = wlp->name[0] & MASK_NAME_SIZE;
+		name = wlp->name + 1;
+
+		if(!isSmudge(wlp) &&
+		   (namelen == wordlen) &&
+		   ffCompareTextCaseN(name, word, wordlen))
+		{
+			return wlp;
+		}
+	}
+	/* not found */
+	return wlp;
+}
+
 /*
 ** ( $name -- $addr 0 | nfa -1 | nfa 1 , find NFA in dictionary )
 ** 1 for IMMEDIATE values
 */
-cell_t ffFindNFA( const ForthString *WordName, const ForthString **NFAPtr )
+cell_t ffFindNFA(const ForthString *name, const ForthString **NFAPtr)
 {
-	const ForthString *WordChar;
-	uint8_t WordLen;
-	const char *NameField, *NameChar;
-	int8_t NameLen;
-	cell_t Searching = TRUE;
-	cell_t Result = 0;
-	
-	WordLen = (uint8_t) ((ucell_t)*WordName & 0x1F);
-	WordChar = WordName+1;
-	
-	NameField = (ForthString *) gVarContext;
-DBUG(("\nffFindNFA: WordLen = %d, WordName = %*s\n", WordLen, WordLen, WordChar ));
-DBUG(("\nffFindNFA: gVarContext = 0x%x\n", gVarContext));
-	do
-	{
-		NameLen = (uint8_t) ((ucell_t)(*NameField) & MASK_NAME_SIZE);
-		NameChar = NameField+1;
-/* DBUG(("   %c\n", (*NameField & FLAG_SMUDGE) ? 'S' : 'V' )); */
-		if(	((*NameField & FLAG_SMUDGE) == 0) &&
-			(NameLen == WordLen) &&
-			ffCompareTextCaseN( NameChar, WordChar, WordLen ) ) /* FIXME - slow */
-		{
-DBUG(("ffFindNFA: found it at NFA = 0x%x\n", NameField));
-			*NFAPtr = NameField ;
-			Result = ((*NameField) & FLAG_IMMEDIATE) ? 1 : -1;
-			Searching = FALSE;
-		}
-		else
-		{
-			NameField = NameToPrevious( NameField );
-			if( NameField == NULL )
-			{
-				*NFAPtr = WordName;
-				Searching = FALSE;
-			}
-		}
-	} while ( Searching);
-DBUG(("ffFindNFA: returns 0x%x\n", Result));
-	return Result;
+	const WordListEntry *wle;
+	cell_t result;
+
+	wle = ffFindEntry(name+1, *(unsigned char*)name & MASK_NAME_SIZE);
+
+	if (wle != NULL) {
+		*NFAPtr = tonfa(wle);
+		result = (isImmediate(wle) ? 1 : -1);
+	} else {
+		*NFAPtr = name;
+		result = 0;
+	}
+
+	return result;
 }
 
 
@@ -488,33 +545,47 @@
 ** ( $name -- $name 0 | xt -1 | xt 1 )
 ** 1 for IMMEDIATE values
 */
-cell_t ffFind( const ForthString *WordName, ExecToken *pXT )
+cell_t ffFind(const ForthString *name, ExecToken *pXT)
 {
-	const ForthString *NFA;
-	cell_t Result;
+	WordListEntry *wle;
+	cell_t result;
 	
-	Result = ffFindNFA( WordName, &NFA );
+	wle = ffFindEntry(name+1, *(unsigned char*)name & MASK_NAME_SIZE);
 DBUG(("ffFind: %8s at 0x%x\n", WordName+1, NFA)); /* WARNING, not NUL terminated. %Q */
-	if( Result )
-	{
-		*pXT = NameToToken( NFA );
+	if (wle != NULL) {
+		*pXT = getAction(wle);
+		result = (isImmediate(wle) ? 1 : -1);
 	}
 	else
 	{
-		*pXT = (ExecToken) WordName;
+		*pXT = (ExecToken) name;
+		result = 0;
 	}
 
-	return Result;
+	return result;
 }
 
 /****************************************************************
 ** Find name when passed 'C' string.
 */
-cell_t ffFindC( const char *WordName, ExecToken *pXT )
+cell_t ffFindC(const char *name, ExecToken *pXT)
 {
-DBUG(("ffFindC: %s\n", WordName ));
-	CStringToForth( gScratch, WordName, sizeof(gScratch) );
-	return ffFind( gScratch, pXT );
+	WordListEntry *wle;
+	cell_t result;
+
+DBUG(("ffFindC: %s\n", name));
+	wle = ffFindEntry(name, strlen(name));
+	if (wle != NULL) {
+		*pXT = getAction(wle);
+		result = (isImmediate(wle) ? 1 : -1);
+	}
+	else
+	{
+		*pXT = (ExecToken) name;
+		result = 0;
+	}
+
+	return result;
 }
 
 
