|
|
1.1 ! root 1: /* ! 2: * tag: dict management ! 3: * ! 4: * Copyright (C) 2003-2005 Stefan Reinauer, Patrick Mauritz ! 5: * ! 6: * See the file "COPYING" for further information about ! 7: * the copyright and warranty status of this work. ! 8: */ ! 9: ! 10: #include "config.h" ! 11: #include "kernel/kernel.h" ! 12: #include "dict.h" ! 13: #ifdef BOOTSTRAP ! 14: #include <string.h> ! 15: #else ! 16: #include "libc/string.h" ! 17: #endif ! 18: #include "cross.h" ! 19: ! 20: ! 21: unsigned char *dict = NULL; ! 22: ucell *last; ! 23: cell dicthead = 0; ! 24: cell dictlimit = 0; ! 25: ! 26: /* lfa2nfa ! 27: * converts a link field address to a name field address, ! 28: * i.e find pointer to a given words name ! 29: */ ! 30: ! 31: ucell lfa2nfa(ucell ilfa) ! 32: { ! 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); ! 39: } ! 40: ! 41: /* lfa2cfa ! 42: * converts a link field address to a code field address. ! 43: * in this forth implementation this is just a fixed offset ! 44: */ ! 45: ! 46: static xt_t lfa2cfa(ucell ilfa) ! 47: { ! 48: return (xt_t)(ilfa + sizeof(cell)); ! 49: } ! 50: ! 51: ! 52: /* fstrlen - returns length of a forth string. */ ! 53: ! 54: ucell fstrlen(ucell fstr) ! 55: { ! 56: fstr -= pointer2cell(dict)+1; ! 57: //fstr -= pointer2cell(dict); FIXME ! 58: while (dict[++fstr] < 128) ! 59: ; ! 60: return dict[fstr] - 128; ! 61: } ! 62: ! 63: /* to_lower - convert a character to lowecase */ ! 64: ! 65: static int to_lower(int c) ! 66: { ! 67: return ((c >= 'A') && (c <= 'Z')) ? (c - 'A' + 'a') : c; ! 68: } ! 69: ! 70: /* fstrcmp - compare null terminated string with forth string. */ ! 71: ! 72: static int fstrcmp(const char *s1, ucell fstr) ! 73: { ! 74: char *s2 = (char*)cell2pointer(fstr); ! 75: while (*s1) { ! 76: if ( to_lower(*(s1++)) != to_lower(*(s2++)) ) ! 77: return -1; ! 78: } ! 79: return 0; ! 80: } ! 81: ! 82: /* fstrncpy - copy a forth string to a destination (with NULL termination) */ ! 83: ! 84: void fstrncpy(char *dest, ucell src, unsigned int maxlen) ! 85: { ! 86: int len = fstrlen(src); ! 87: ! 88: if (fstrlen(src) >= maxlen) len = maxlen - 1; ! 89: memcpy(dest, cell2pointer(src), len); ! 90: *(dest + len) = '\0'; ! 91: } ! 92: ! 93: ! 94: /* findword ! 95: * looks up a given word in the dictionary. This function ! 96: * is used by the c based interpreter and to find the "initialize" ! 97: * word. ! 98: */ ! 99: ! 100: xt_t findword(const char *s1) ! 101: { ! 102: ucell tmplfa, len; ! 103: ! 104: if (!last) ! 105: return 0; ! 106: ! 107: tmplfa = read_ucell(last); ! 108: ! 109: len = strlen(s1); ! 110: ! 111: while (tmplfa) { ! 112: ucell nfa = lfa2nfa(tmplfa); ! 113: ! 114: if (len == fstrlen(nfa) && !fstrcmp(s1, nfa)) { ! 115: return lfa2cfa(tmplfa); ! 116: } ! 117: ! 118: tmplfa = read_ucell(cell2pointer(tmplfa)); ! 119: } ! 120: ! 121: return 0; ! 122: } ! 123: ! 124: ! 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 ! 129: * from the NFA. ! 130: */ ! 131: ! 132: static ucell findsemis_wordlist(ucell xt, ucell wordlist) ! 133: { ! 134: ucell tmplfa, nextlfa, nextcfa; ! 135: ! 136: if (!wordlist) ! 137: return 0; ! 138: ! 139: tmplfa = read_ucell(cell2pointer(wordlist)); ! 140: nextcfa = lfa2cfa(tmplfa); ! 141: ! 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 */ ! 145: if (nextcfa == xt) ! 146: return pointer2cell(dict) + dicthead - sizeof(cell); ! 147: ! 148: while (tmplfa) { ! 149: ! 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); ! 154: ! 155: /* If so, count back 1 cell from the current NFA */ ! 156: if (nextcfa == xt) ! 157: return lfa2nfa(tmplfa) - sizeof(cell); ! 158: ! 159: tmplfa = nextlfa; ! 160: } ! 161: ! 162: return 0; ! 163: } ! 164: ! 165: ! 166: /* findsemis ! 167: * Given a DOCOL xt, find the address of the semis word at the end ! 168: * of the word definition by searching all vocabularies */ ! 169: ! 170: ucell findsemis(ucell xt) ! 171: { ! 172: ucell usesvocab = findword("vocabularies?") + sizeof(cell); ! 173: unsigned int i; ! 174: ! 175: if (read_ucell(cell2pointer(usesvocab))) { ! 176: /* Vocabularies are in use, so search each one in turn */ ! 177: ucell numvocabs = findword("#order") + sizeof(cell); ! 178: ! 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))))); ! 182: ! 183: /* If we get a non-zero result, we found the xt in this vocab */ ! 184: if (semis) ! 185: return semis; ! 186: } ! 187: } else { ! 188: /* Vocabularies not in use */ ! 189: return findsemis_wordlist(xt, read_ucell(last)); ! 190: } ! 191: ! 192: return 0; ! 193: } ! 194: ! 195: ! 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 ! 199: */ ! 200: ! 201: ucell findxtfromcell_wordlist(ucell incell, ucell wordlist) ! 202: { ! 203: ucell tmplfa; ! 204: ! 205: if (!wordlist) ! 206: return 0; ! 207: ! 208: tmplfa = read_ucell(cell2pointer(wordlist)); ! 209: while (tmplfa) { ! 210: if (tmplfa < incell) ! 211: return lfa2cfa(tmplfa); ! 212: ! 213: tmplfa = read_ucell(cell2pointer(tmplfa)); ! 214: } ! 215: ! 216: return 0; ! 217: } ! 218: ! 219: ! 220: /* findxtfromcell ! 221: * Given a cell, determine the CFA of the word containing ! 222: * the cell by searching all vocabularies ! 223: */ ! 224: ! 225: ucell findxtfromcell(ucell incell) ! 226: { ! 227: ucell usesvocab = findword("vocabularies?") + sizeof(cell); ! 228: unsigned int i; ! 229: ! 230: if (read_ucell(cell2pointer(usesvocab))) { ! 231: /* Vocabularies are in use, so search each one in turn */ ! 232: ucell numvocabs = findword("#order") + sizeof(cell); ! 233: ! 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))))); ! 237: ! 238: /* If we get a non-zero result, we found the xt in this vocab */ ! 239: if (semis) ! 240: return semis; ! 241: } ! 242: } else { ! 243: /* Vocabularies not in use */ ! 244: return findxtfromcell_wordlist(incell, read_ucell(last)); ! 245: } ! 246: ! 247: return 0; ! 248: } ! 249: ! 250: void dump_header(dictionary_header_t *header) ! 251: { ! 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)); ! 261: } ! 262: ! 263: ucell load_dictionary(const char *data, ucell len) ! 264: { ! 265: u32 checksum=0; ! 266: const char *checksum_walk; ! 267: ucell *walk, *reloc_table; ! 268: dictionary_header_t *header=(dictionary_header_t *)data; ! 269: ! 270: /* assertions */ ! 271: if (len <= (sizeof(dictionary_header_t)) || strncmp(DICTID, data, 8)) ! 272: return 0; ! 273: #ifdef CONFIG_DEBUG_DICTIONARY ! 274: dump_header(header); ! 275: #endif ! 276: ! 277: checksum_walk=data; ! 278: while (checksum_walk<data+len) { ! 279: checksum+=read_long(checksum_walk); ! 280: checksum_walk+=sizeof(u32); ! 281: } ! 282: ! 283: if(checksum) { ! 284: printk("Checksum invalid (%08x)!\n", checksum); ! 285: return 0; ! 286: } ! 287: ! 288: data += sizeof(dictionary_header_t); ! 289: ! 290: dicthead = target_long(header->length); ! 291: ! 292: memcpy(dict, data, dicthead); ! 293: reloc_table=(ucell *)(data+dicthead); ! 294: ! 295: #ifdef CONFIG_DEBUG_DICTIONARY ! 296: printk("\nmoving dictionary (%x bytes) to %x\n", ! 297: (ucell)dicthead, (ucell)dict); ! 298: printk("\ndynamic relocation..."); ! 299: #endif ! 300: ! 301: for (walk = (ucell *) dict; walk < (ucell *) (dict + dicthead); ! 302: walk++) { ! 303: int pos, bit, l; ! 304: l=(walk-(ucell *)dict); ! 305: pos=l/BITS; ! 306: bit=l&~(-BITS); ! 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)); ! 310: } ! 311: } ! 312: ! 313: #ifdef CONFIG_DEBUG_DICTIONARY ! 314: printk(" done.\n"); ! 315: #endif ! 316: ! 317: last = (ucell *)(dict + target_ucell(header->last)); ! 318: ! 319: return -1; ! 320: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.