From 9e80202352dd49bdd9e67b8b906d86f058431505 Mon Sep 17 00:00:00 2001
From: Timothy Pearson <tpearson@raptorengineering.com>
Date: Sat, 11 May 2019 15:12:49 -0500
Subject: Initial import of abandoned HQEMU version 2.5.2

---
 src/roms/openbios/kernel/dict.c | 320 ++++++++++++++++++++++++++++++++++++++++
 1 file changed, 320 insertions(+)
 create mode 100644 src/roms/openbios/kernel/dict.c

(limited to 'src/roms/openbios/kernel/dict.c')

diff --git a/src/roms/openbios/kernel/dict.c b/src/roms/openbios/kernel/dict.c
new file mode 100644
index 0000000..0986cb1
--- /dev/null
+++ b/src/roms/openbios/kernel/dict.c
@@ -0,0 +1,320 @@
+/*
+ * tag: dict management
+ *
+ * Copyright (C) 2003-2005 Stefan Reinauer, Patrick Mauritz
+ *
+ * See the file "COPYING" for further information about
+ * the copyright and warranty status of this work.
+ */
+
+#include "config.h"
+#include "kernel/kernel.h"
+#include "dict.h"
+#ifdef BOOTSTRAP
+#include <string.h>
+#else
+#include "libc/string.h"
+#endif
+#include "cross.h"
+
+
+unsigned char *dict = NULL;
+ucell *last;
+cell dicthead = 0;
+cell dictlimit = 0;
+
+/* lfa2nfa
+ * converts a link field address to a name field address,
+ * i.e find pointer to a given words name
+ */
+
+ucell lfa2nfa(ucell ilfa)
+{
+	/* get offset from dictionary start */
+	ilfa = ilfa - (ucell)pointer2cell(dict);
+	ilfa--;				/* skip status        */
+	while (dict[--ilfa] == 0);	/* skip all pad bytes */
+	ilfa -= (dict[ilfa] - 128);
+	return ilfa + (ucell)pointer2cell(dict);
+}
+
+/* lfa2cfa
+ * converts a link field address to a code field address.
+ * in this forth implementation this is just a fixed offset
+ */
+
+static xt_t lfa2cfa(ucell ilfa)
+{
+	return (xt_t)(ilfa + sizeof(cell));
+}
+
+
+/* fstrlen - returns length of a forth string. */
+
+ucell fstrlen(ucell fstr)
+{
+	fstr -= pointer2cell(dict)+1;
+	//fstr -= pointer2cell(dict); FIXME
+	while (dict[++fstr] < 128)
+		;
+	return dict[fstr] - 128;
+}
+
+/* to_lower - convert a character to lowecase */
+
+static int to_lower(int c)
+{
+	return ((c >= 'A') && (c <= 'Z')) ? (c - 'A' + 'a') : c;
+}
+
+/* fstrcmp - compare null terminated string with forth string. */
+
+static int fstrcmp(const char *s1, ucell fstr)
+{
+	char *s2 = (char*)cell2pointer(fstr);
+	while (*s1) {
+		if ( to_lower(*(s1++)) != to_lower(*(s2++)) )
+			return -1;
+	}
+	return 0;
+}
+
+/* fstrncpy - copy a forth string to a destination (with NULL termination) */
+
+void fstrncpy(char *dest, ucell src, unsigned int maxlen)
+{
+	int len = fstrlen(src);
+
+	if (fstrlen(src) >= maxlen) len = maxlen - 1;
+	memcpy(dest, cell2pointer(src), len);
+	*(dest + len) = '\0';
+} 
+
+
+/* findword
+ * looks up a given word in the dictionary. This function
+ * is used by the c based interpreter and to find the "initialize"
+ * word.
+ */
+
+xt_t findword(const char *s1)
+{
+	ucell tmplfa, len;
+
+	if (!last)
+		return 0;
+
+	tmplfa = read_ucell(last);
+
+	len = strlen(s1);
+
+	while (tmplfa) {
+		ucell nfa = lfa2nfa(tmplfa);
+
+		if (len == fstrlen(nfa) && !fstrcmp(s1, nfa)) {
+			return lfa2cfa(tmplfa);
+		}
+
+		tmplfa = read_ucell(cell2pointer(tmplfa));
+	}
+
+	return 0;
+}
+
+
+/* findsemis_wordlist
+ * Given a DOCOL xt and a wordlist, find the address of the semis
+ * word at the end of the word definition. We do this by finding
+ * the word before this in the dictionary, then counting back one
+ * from the NFA.
+ */
+
+static ucell findsemis_wordlist(ucell xt, ucell wordlist)
+{
+	ucell tmplfa, nextlfa, nextcfa;
+
+	if (!wordlist)
+		return 0;
+
+	tmplfa = read_ucell(cell2pointer(wordlist));
+	nextcfa = lfa2cfa(tmplfa);
+
+	/* Catch the special case where the lfa of the word we
+	 * want is the last word in the dictionary; in that case
+	 * the end of the word is given by "here" - 1 */
+	if (nextcfa == xt)
+		return pointer2cell(dict) + dicthead - sizeof(cell);
+
+	while (tmplfa) {
+
+		/* Peek ahead and see if the next CFA in the list is the
+		 * one we are searching for */ 
+		nextlfa = read_ucell(cell2pointer(tmplfa)); 
+		nextcfa = lfa2cfa(nextlfa);
+
+		/* If so, count back 1 cell from the current NFA */
+		if (nextcfa == xt)
+			return lfa2nfa(tmplfa) - sizeof(cell);
+
+		tmplfa = nextlfa;
+	}
+
+	return 0;
+}
+
+
+/* findsemis
+ * Given a DOCOL xt, find the address of the semis word at the end
+ * of the word definition by searching all vocabularies */
+
+ucell findsemis(ucell xt)
+{
+	ucell usesvocab = findword("vocabularies?") + sizeof(cell);
+	unsigned int i;
+
+	if (read_ucell(cell2pointer(usesvocab))) {
+		/* Vocabularies are in use, so search each one in turn */
+		ucell numvocabs = findword("#order") + sizeof(cell);
+
+		for (i = 0; i < read_ucell(cell2pointer(numvocabs)); i++) {
+			ucell vocabs = findword("vocabularies") + 2 * sizeof(cell);
+			ucell semis = findsemis_wordlist(xt, read_cell(cell2pointer(vocabs + (i * sizeof(cell))))); 	
+
+			/* If we get a non-zero result, we found the xt in this vocab */
+			if (semis)
+				return semis;
+		}
+	} else { 
+		/* Vocabularies not in use */
+		return findsemis_wordlist(xt, read_ucell(last));
+	}
+
+	return 0;
+}
+
+
+/* findxtfromcell_wordlist
+ * Given a cell and a wordlist, determine the CFA of the word containing
+ * the cell or 0 if we are unable to return a suitable CFA
+ */
+
+ucell findxtfromcell_wordlist(ucell incell, ucell wordlist)
+{
+	ucell tmplfa;
+
+	if (!wordlist)
+		return 0;
+
+	tmplfa = read_ucell(cell2pointer(wordlist));
+	while (tmplfa) {
+		if (tmplfa < incell)
+			return lfa2cfa(tmplfa);
+
+		tmplfa = read_ucell(cell2pointer(tmplfa));
+	}	
+
+	return 0;
+} 
+
+
+/* findxtfromcell
+ * Given a cell, determine the CFA of the word containing
+ * the cell by searching all vocabularies 
+ */
+
+ucell findxtfromcell(ucell incell)
+{
+	ucell usesvocab = findword("vocabularies?") + sizeof(cell);
+	unsigned int i;
+
+	if (read_ucell(cell2pointer(usesvocab))) {
+		/* Vocabularies are in use, so search each one in turn */
+		ucell numvocabs = findword("#order") + sizeof(cell);
+
+		for (i = 0; i < read_ucell(cell2pointer(numvocabs)); i++) {
+			ucell vocabs = findword("vocabularies") + 2 * sizeof(cell);
+			ucell semis = findxtfromcell_wordlist(incell, read_cell(cell2pointer(vocabs + (i * sizeof(cell))))); 	
+
+			/* If we get a non-zero result, we found the xt in this vocab */
+			if (semis)
+				return semis;
+		}
+	} else { 
+		/* Vocabularies not in use */
+		return findxtfromcell_wordlist(incell, read_ucell(last));
+	}
+
+	return 0;
+}
+
+void dump_header(dictionary_header_t *header)
+{
+	printk("OpenBIOS dictionary:\n");
+	printk("  version:     %d\n", header->version);
+	printk("  cellsize:    %d\n", header->cellsize);
+	printk("  endianess:   %s\n", header->endianess?"big":"little");
+	printk("  compression: %s\n", header->compression?"yes":"no");
+	printk("  relocation:  %s\n", header->relocation?"yes":"no");
+	printk("  checksum:    %08x\n", target_long(header->checksum));
+	printk("  length:      %08x\n", target_long(header->length));
+	printk("  last:        %0" FMT_CELL_x "\n", target_cell(header->last));
+}
+
+ucell load_dictionary(const char *data, ucell len)
+{
+	u32 checksum=0;
+	const char *checksum_walk;
+	ucell *walk, *reloc_table;
+	dictionary_header_t *header=(dictionary_header_t *)data;
+
+	/* assertions */
+	if (len <= (sizeof(dictionary_header_t)) || strncmp(DICTID, data, 8))
+		return 0;
+#ifdef CONFIG_DEBUG_DICTIONARY
+	dump_header(header);
+#endif
+
+	checksum_walk=data;
+	while (checksum_walk<data+len) {
+		checksum+=read_long(checksum_walk);
+		checksum_walk+=sizeof(u32);
+	}
+
+	if(checksum) {
+		printk("Checksum invalid (%08x)!\n", checksum);
+		return 0;
+	}
+
+	data += sizeof(dictionary_header_t);
+
+	dicthead = target_long(header->length);
+
+	memcpy(dict, data, dicthead);
+	reloc_table=(ucell *)(data+dicthead);
+
+#ifdef CONFIG_DEBUG_DICTIONARY
+	printk("\nmoving dictionary (%x bytes) to %x\n",
+			(ucell)dicthead, (ucell)dict);
+	printk("\ndynamic relocation...");
+#endif
+
+	for (walk = (ucell *) dict; walk < (ucell *) (dict + dicthead);
+	     walk++) {
+		int pos, bit, l;
+		l=(walk-(ucell *)dict);
+		pos=l/BITS;
+		bit=l&~(-BITS);
+                if (reloc_table[pos] & target_ucell((ucell)1ULL << bit)) {
+			// printk("%lx, pos %x, bit %d\n",*walk, pos, bit);
+			write_ucell(walk, read_ucell(walk)+pointer2cell(dict));
+		}
+	}
+
+#ifdef CONFIG_DEBUG_DICTIONARY
+	printk(" done.\n");
+#endif
+
+	last = (ucell *)(dict + target_ucell(header->last));
+
+	return -1;
+}
-- 
cgit v1.1