4 * Copyright (C) 2003-2005 Stefan Reinauer, Patrick Mauritz
6 * See the file "COPYING" for further information about
7 * the copyright and warranty status of this work.
11 #include "kernel/kernel.h"
16 #include "libc/string.h"
21 unsigned char *dict
= NULL
;
27 * converts a link field address to a name field address,
28 * i.e find pointer to a given words name
31 ucell
lfa2nfa(ucell ilfa
)
33 /* get offset from dictionary start */
34 ilfa
= ilfa
- (ucell
)pointer2cell(dict
);
35 ilfa
--; /* skip status */
36 while (dict
[--ilfa
] == 0); /* skip all pad bytes */
37 ilfa
-= (dict
[ilfa
] - 128);
38 return ilfa
+ (ucell
)pointer2cell(dict
);
42 * converts a link field address to a code field address.
43 * in this forth implementation this is just a fixed offset
46 static xt_t
lfa2cfa(ucell ilfa
)
48 return (xt_t
)(ilfa
+ sizeof(cell
));
52 /* fstrlen - returns length of a forth string. */
54 ucell
fstrlen(ucell fstr
)
56 fstr
-= pointer2cell(dict
)+1;
57 //fstr -= pointer2cell(dict); FIXME
58 while (dict
[++fstr
] < 128)
60 return dict
[fstr
] - 128;
63 /* to_lower - convert a character to lowecase */
65 static int to_lower(int c
)
67 return ((c
>= 'A') && (c
<= 'Z')) ? (c
- 'A' + 'a') : c
;
70 /* fstrcmp - compare null terminated string with forth string. */
72 static int fstrcmp(const char *s1
, ucell fstr
)
74 char *s2
= (char*)cell2pointer(fstr
);
76 if ( to_lower(*(s1
++)) != to_lower(*(s2
++)) )
82 /* fstrncpy - copy a forth string to a destination (with NULL termination) */
84 void fstrncpy(char *dest
, ucell src
, unsigned int maxlen
)
86 int len
= fstrlen(src
);
88 if (fstrlen(src
) >= maxlen
) len
= maxlen
- 1;
89 memcpy(dest
, cell2pointer(src
), len
);
95 * looks up a given word in the dictionary. This function
96 * is used by the c based interpreter and to find the "initialize"
100 xt_t
findword(const char *s1
)
107 tmplfa
= read_ucell(last
);
112 ucell nfa
= lfa2nfa(tmplfa
);
114 if (len
== fstrlen(nfa
) && !fstrcmp(s1
, nfa
)) {
115 return lfa2cfa(tmplfa
);
118 tmplfa
= read_ucell(cell2pointer(tmplfa
));
125 /* findsemis_wordlist
126 * Given a DOCOL xt and a wordlist, find the address of the semis
127 * word at the end of the word definition. We do this by finding
128 * the word before this in the dictionary, then counting back one
132 static ucell
findsemis_wordlist(ucell xt
, ucell wordlist
)
134 ucell tmplfa
, nextlfa
, nextcfa
;
139 tmplfa
= read_ucell(cell2pointer(wordlist
));
140 nextcfa
= lfa2cfa(tmplfa
);
142 /* Catch the special case where the lfa of the word we
143 * want is the last word in the dictionary; in that case
144 * the end of the word is given by "here" - 1 */
146 return pointer2cell(dict
) + dicthead
- sizeof(cell
);
150 /* Peek ahead and see if the next CFA in the list is the
151 * one we are searching for */
152 nextlfa
= read_ucell(cell2pointer(tmplfa
));
153 nextcfa
= lfa2cfa(nextlfa
);
155 /* If so, count back 1 cell from the current NFA */
157 return lfa2nfa(tmplfa
) - sizeof(cell
);
167 * Given a DOCOL xt, find the address of the semis word at the end
168 * of the word definition by searching all vocabularies */
170 ucell
findsemis(ucell xt
)
172 ucell usesvocab
= findword("vocabularies?") + sizeof(cell
);
175 if (read_ucell(cell2pointer(usesvocab
))) {
176 /* Vocabularies are in use, so search each one in turn */
177 ucell numvocabs
= findword("#order") + sizeof(cell
);
179 for (i
= 0; i
< read_ucell(cell2pointer(numvocabs
)); i
++) {
180 ucell vocabs
= findword("vocabularies") + 2 * sizeof(cell
);
181 ucell semis
= findsemis_wordlist(xt
, read_cell(cell2pointer(vocabs
+ (i
* sizeof(cell
)))));
183 /* If we get a non-zero result, we found the xt in this vocab */
188 /* Vocabularies not in use */
189 return findsemis_wordlist(xt
, read_ucell(last
));
196 /* findxtfromcell_wordlist
197 * Given a cell and a wordlist, determine the CFA of the word containing
198 * the cell or 0 if we are unable to return a suitable CFA
201 ucell
findxtfromcell_wordlist(ucell incell
, ucell wordlist
)
208 tmplfa
= read_ucell(cell2pointer(wordlist
));
211 return lfa2cfa(tmplfa
);
213 tmplfa
= read_ucell(cell2pointer(tmplfa
));
221 * Given a cell, determine the CFA of the word containing
222 * the cell by searching all vocabularies
225 ucell
findxtfromcell(ucell incell
)
227 ucell usesvocab
= findword("vocabularies?") + sizeof(cell
);
230 if (read_ucell(cell2pointer(usesvocab
))) {
231 /* Vocabularies are in use, so search each one in turn */
232 ucell numvocabs
= findword("#order") + sizeof(cell
);
234 for (i
= 0; i
< read_ucell(cell2pointer(numvocabs
)); i
++) {
235 ucell vocabs
= findword("vocabularies") + 2 * sizeof(cell
);
236 ucell semis
= findxtfromcell_wordlist(incell
, read_cell(cell2pointer(vocabs
+ (i
* sizeof(cell
)))));
238 /* If we get a non-zero result, we found the xt in this vocab */
243 /* Vocabularies not in use */
244 return findxtfromcell_wordlist(incell
, read_ucell(last
));
250 void dump_header(dictionary_header_t
*header
)
252 printk("OpenBIOS dictionary:\n");
253 printk(" version: %d\n", header
->version
);
254 printk(" cellsize: %d\n", header
->cellsize
);
255 printk(" endianess: %s\n", header
->endianess
?"big":"little");
256 printk(" compression: %s\n", header
->compression
?"yes":"no");
257 printk(" relocation: %s\n", header
->relocation
?"yes":"no");
258 printk(" checksum: %08x\n", target_long(header
->checksum
));
259 printk(" length: %08x\n", target_long(header
->length
));
260 printk(" last: %0" FMT_CELL_x
"\n", target_cell(header
->last
));
263 ucell
load_dictionary(const char *data
, ucell len
)
266 const char *checksum_walk
;
267 ucell
*walk
, *reloc_table
;
268 dictionary_header_t
*header
=(dictionary_header_t
*)data
;
271 if (len
<= (sizeof(dictionary_header_t
)) || strncmp(DICTID
, data
, 8))
273 #ifdef CONFIG_DEBUG_DICTIONARY
278 while (checksum_walk
<data
+len
) {
279 checksum
+=read_long(checksum_walk
);
280 checksum_walk
+=sizeof(u32
);
284 printk("Checksum invalid (%08x)!\n", checksum
);
288 data
+= sizeof(dictionary_header_t
);
290 dicthead
= target_long(header
->length
);
292 memcpy(dict
, data
, dicthead
);
293 reloc_table
=(ucell
*)(data
+dicthead
);
295 #ifdef CONFIG_DEBUG_DICTIONARY
296 printk("\nmoving dictionary (%x bytes) to %x\n",
297 (ucell
)dicthead
, (ucell
)dict
);
298 printk("\ndynamic relocation...");
301 for (walk
= (ucell
*) dict
; walk
< (ucell
*) (dict
+ dicthead
);
304 l
=(walk
-(ucell
*)dict
);
307 if (reloc_table
[pos
] & target_ucell((ucell
)1ULL << bit
)) {
308 // printk("%lx, pos %x, bit %d\n",*walk, pos, bit);
309 write_ucell(walk
, read_ucell(walk
)+pointer2cell(dict
));
313 #ifdef CONFIG_DEBUG_DICTIONARY
317 last
= (ucell
*)(dict
+ target_ucell(header
->last
));