aboutsummaryrefslogtreecommitdiff
path: root/engines/sci
diff options
context:
space:
mode:
authorFilippos Karapetis2009-05-31 12:05:49 +0000
committerFilippos Karapetis2009-05-31 12:05:49 +0000
commite317012cce8647a9d50f185cdba5bafc7c48c9a2 (patch)
treec353e167139efea2e04cb6ef090e14477327c47a /engines/sci
parent555d4038cc053c0c914dd1cb56746066446a1386 (diff)
downloadscummvm-rg350-e317012cce8647a9d50f185cdba5bafc7c48c9a2.tar.gz
scummvm-rg350-e317012cce8647a9d50f185cdba5bafc7c48c9a2.tar.bz2
scummvm-rg350-e317012cce8647a9d50f185cdba5bafc7c48c9a2.zip
Further objectification of the SCI vocabulary functions. Removed the "kernel_words" console command, as it's exactly the same as "parser_words"
svn-id: r41065
Diffstat (limited to 'engines/sci')
-rw-r--r--engines/sci/console.cpp66
-rw-r--r--engines/sci/console.h1
-rw-r--r--engines/sci/engine/game.cpp4
-rw-r--r--engines/sci/engine/grammar.cpp59
-rw-r--r--engines/sci/engine/kernel.cpp393
-rw-r--r--engines/sci/engine/kstring.cpp5
-rw-r--r--engines/sci/engine/said.cpp2
-rw-r--r--engines/sci/engine/said.y2
-rw-r--r--engines/sci/engine/savegame.cpp5
-rw-r--r--engines/sci/engine/scriptdebug.cpp2
-rw-r--r--engines/sci/engine/state.cpp1
-rw-r--r--engines/sci/engine/state.h1
-rw-r--r--engines/sci/vocabulary.cpp464
-rw-r--r--engines/sci/vocabulary.h181
14 files changed, 606 insertions, 580 deletions
diff --git a/engines/sci/console.cpp b/engines/sci/console.cpp
index feb5977ae8..96f000d9c0 100644
--- a/engines/sci/console.cpp
+++ b/engines/sci/console.cpp
@@ -56,7 +56,8 @@ Console::Console(SciEngine *vm) : GUI::Debugger() {
DCmd_Register("selectors", WRAP_METHOD(Console, cmdSelectors));
DCmd_Register("kernel_names", WRAP_METHOD(Console, cmdKernelNames));
DCmd_Register("suffixes", WRAP_METHOD(Console, cmdSuffixes));
- DCmd_Register("kernel_words", WRAP_METHOD(Console, cmdKernelWords));
+ DCmd_Register("parser_nodes", WRAP_METHOD(Console, cmdParserNodes));
+ DCmd_Register("parser_words", WRAP_METHOD(Console, cmdParserWords));
DCmd_Register("hexdump", WRAP_METHOD(Console, cmdHexDump));
DCmd_Register("dissect_script", WRAP_METHOD(Console, cmdDissectScript));
DCmd_Register("room", WRAP_METHOD(Console, cmdRoomNumber));
@@ -72,8 +73,6 @@ Console::Console(SciEngine *vm) : GUI::Debugger() {
DCmd_Register("restart_game", WRAP_METHOD(Console, cmdRestartGame));
DCmd_Register("class_table", WRAP_METHOD(Console, cmdClassTable));
DCmd_Register("sentence_fragments", WRAP_METHOD(Console, cmdSentenceFragments));
- DCmd_Register("parser_nodes", WRAP_METHOD(Console, cmdParserNodes));
- DCmd_Register("parser_words", WRAP_METHOD(Console, cmdParserWords));
DCmd_Register("draw_pic", WRAP_METHOD(Console, cmdDrawPic));
DCmd_Register("draw_rect", WRAP_METHOD(Console, cmdDrawRect));
DCmd_Register("fill_screen", WRAP_METHOD(Console, cmdFillScreen));
@@ -174,32 +173,13 @@ bool Console::cmdKernelNames(int argc, const char **argv) {
}
bool Console::cmdSuffixes(int argc, const char **argv) {
- char word_buf[256], alt_buf[256];
-
- int i = 0;
- for (SuffixList::const_iterator suf = g_EngineState->_vocabulary->_parserSuffixes.begin(); suf != g_EngineState->_vocabulary->_parserSuffixes.end(); ++suf) {
- strncpy(word_buf, suf->word_suffix, suf->word_suffix_length);
- word_buf[suf->word_suffix_length] = 0;
- strncpy(alt_buf, suf->alt_suffix, suf->alt_suffix_length);
- alt_buf[suf->alt_suffix_length] = 0;
-
- DebugPrintf("%4d: (%03x) -%12s => -%12s (%03x)\n", i, suf->class_mask, word_buf, alt_buf, suf->result_class);
- ++i;
- }
+ g_EngineState->_vocabulary->printSuffixes();
return true;
}
-bool Console::cmdKernelWords(int argc, const char **argv) {
- int j = 0;
- for (WordMap::iterator i = g_EngineState->_vocabulary->_parserWords.begin(); i != g_EngineState->_vocabulary->_parserWords.end(); ++i) {
- DebugPrintf("%4d: %03x [%03x] %20s |", j, i->_value._class, i->_value._group, i->_key.c_str());
- if (j % 3 == 0)
- DebugPrintf("\n");
- j++;
- }
-
- DebugPrintf("\n");
+bool Console::cmdParserWords(int argc, const char **argv) {
+ g_EngineState->_vocabulary->printParserWords();
return true;
}
@@ -518,32 +498,32 @@ bool Console::cmdClassTable(int argc, const char **argv) {
bool Console::cmdSentenceFragments(int argc, const char **argv) {
DebugPrintf("Sentence fragments (used to build Parse trees\n");
- for (uint i = 0; i < g_EngineState->_vocabulary->_parserBranches.size(); i++) {
+ for (uint i = 0; i < g_EngineState->_vocabulary->getParserBranchesSize(); i++) {
int j = 0;
- DebugPrintf("R%02d: [%x] ->", i, g_EngineState->_vocabulary->_parserBranches[i].id);
- while ((j < 10) && g_EngineState->_vocabulary->_parserBranches[i].data[j]) {
- int dat = g_EngineState->_vocabulary->_parserBranches[i].data[j++];
+ DebugPrintf("R%02d: [%x] ->", i, g_EngineState->_vocabulary->getParseTreeBranch(i).id);
+ while ((j < 10) && g_EngineState->_vocabulary->getParseTreeBranch(i).data[j]) {
+ int dat = g_EngineState->_vocabulary->getParseTreeBranch(i).data[j++];
switch (dat) {
case VOCAB_TREE_NODE_COMPARE_TYPE:
- dat = g_EngineState->_vocabulary->_parserBranches[i].data[j++];
+ dat = g_EngineState->_vocabulary->getParseTreeBranch(i).data[j++];
DebugPrintf(" C(%x)", dat);
break;
case VOCAB_TREE_NODE_COMPARE_GROUP:
- dat = g_EngineState->_vocabulary->_parserBranches[i].data[j++];
+ dat = g_EngineState->_vocabulary->getParseTreeBranch(i).data[j++];
DebugPrintf(" WG(%x)", dat);
break;
case VOCAB_TREE_NODE_FORCE_STORAGE:
- dat = g_EngineState->_vocabulary->_parserBranches[i].data[j++];
+ dat = g_EngineState->_vocabulary->getParseTreeBranch(i).data[j++];
DebugPrintf(" FORCE(%x)", dat);
break;
default:
if (dat > VOCAB_TREE_NODE_LAST_WORD_STORAGE) {
- int dat2 = g_EngineState->_vocabulary->_parserBranches[i].data[j++];
+ int dat2 = g_EngineState->_vocabulary->getParseTreeBranch(i).data[j++];
DebugPrintf(" %x[%x]", dat, dat2);
} else
DebugPrintf(" ?%x?", dat);
@@ -552,7 +532,7 @@ bool Console::cmdSentenceFragments(int argc, const char **argv) {
DebugPrintf("\n");
}
- DebugPrintf("%d rules.\n", g_EngineState->_vocabulary->_parserBranches.size());
+ DebugPrintf("%d rules.\n", g_EngineState->_vocabulary->getParserBranchesSize());
return true;
}
@@ -579,20 +559,6 @@ bool Console::cmdParserNodes(int argc, const char **argv) {
return true;
}
-bool Console::cmdParserWords(int argc, const char **argv) {
- if (g_EngineState->_vocabulary->_parserWords.empty()) {
- DebugPrintf("No words.\n");
- return true;
- }
-
- for (WordMap::iterator i = g_EngineState->_vocabulary->_parserWords.begin(); i != g_EngineState->_vocabulary->_parserWords.end(); ++i)
- DebugPrintf("%s: C %03x G %03x\n", i->_key.c_str(), i->_value._class, i->_value._group);
-
- DebugPrintf("%d words\n", g_EngineState->_vocabulary->_parserWords.size());
-
- return true;
-}
-
bool Console::cmdDrawPic(int argc, const char **argv) {
if (argc < 2) {
DebugPrintf("Draws a pic resource\n");
@@ -696,9 +662,7 @@ bool Console::cmdPrintPort(int argc, const char **argv) {
bool Console::cmdParseGrammar(int argc, const char **argv) {
DebugPrintf("Parse grammar, in strict GNF:\n");
- parse_rule_list_t *tlist = vocab_build_gnf(g_EngineState->_vocabulary->_parserBranches, 1);
- DebugPrintf("%d allocd rules\n", getAllocatedRulesCount());
- vocab_free_rule_list(tlist);
+ g_EngineState->_vocabulary->buildGNF(true);
return true;
}
diff --git a/engines/sci/console.h b/engines/sci/console.h
index 3e79e7d11d..f4033e18eb 100644
--- a/engines/sci/console.h
+++ b/engines/sci/console.h
@@ -46,7 +46,6 @@ private:
bool cmdSelectors(int argc, const char **argv);
bool cmdKernelNames(int argc, const char **argv);
bool cmdSuffixes(int argc, const char **argv);
- bool cmdKernelWords(int argc, const char **argv);
bool cmdHexDump(int argc, const char **argv);
bool cmdDissectScript(int argc, const char **argv);
bool cmdRoomNumber(int argc, const char **argv);
diff --git a/engines/sci/engine/game.cpp b/engines/sci/engine/game.cpp
index 2bacadf769..0355bb3966 100644
--- a/engines/sci/engine/game.cpp
+++ b/engines/sci/engine/game.cpp
@@ -372,7 +372,7 @@ int script_init_engine(EngineState *s, sci_version_t version) {
s->parser_lastmatch_word = SAID_NO_MATCH;
- s->_vocabulary = new Vocabulary(s);
+ s->_vocabulary = new Vocabulary(s->resmgr, (s->flags & GF_SCI0_OLD));
script_map_kernel(s);
// Maps the kernel functions
@@ -422,8 +422,6 @@ void script_free_engine(EngineState *s) {
s->_kfuncTable.clear();
- vocab_free_rule_list(s->parser_rules);
-
delete s->_vocabulary;
}
diff --git a/engines/sci/engine/grammar.cpp b/engines/sci/engine/grammar.cpp
index 8da1bae370..b54815176e 100644
--- a/engines/sci/engine/grammar.cpp
+++ b/engines/sci/engine/grammar.cpp
@@ -30,6 +30,7 @@
#include "sci/tools.h"
#include "sci/vocabulary.h"
+#include "sci/console.h"
namespace Sci {
@@ -229,10 +230,10 @@ static parse_rule_t *_vsatisfy_rule(parse_rule_t *rule, const ResultWord &input)
return NULL;
}
-void vocab_free_rule_list(parse_rule_list_t *list) {
+void Vocabulary::freeRuleList(parse_rule_list_t *list) {
if (list) {
_vfree(list->rule);
- vocab_free_rule_list(list->next); // Yep, this is slow and memory-intensive.
+ freeRuleList(list->next); // Yep, this is slow and memory-intensive.
free(list);
}
}
@@ -344,15 +345,16 @@ static parse_rule_list_t *_vocab_clone_rule_list_by_id(parse_rule_list_t *list,
return result;
}
-parse_rule_list_t *vocab_build_gnf(const Common::Array<parse_tree_branch_t> &branches, int verbose) {
+parse_rule_list_t *Vocabulary::buildGNF(bool verbose) {
int iterations = 0;
int last_termrules, termrules = 0;
int ntrules_nr;
parse_rule_list_t *ntlist = NULL;
parse_rule_list_t *tlist, *new_tlist;
+ Sci::Console *con = ((SciEngine *)g_engine)->_console;
- for (uint i = 1; i < branches.size(); i++) { // branch rule 0 is treated specially
- parse_rule_t *rule = _vbuild_rule(&branches[i]);
+ for (uint i = 1; i < _parserBranches.size(); i++) { // branch rule 0 is treated specially
+ parse_rule_t *rule = _vbuild_rule(&_parserBranches[i]);
if (!rule)
return NULL;
ntlist = _vocab_add_rule(ntlist, rule);
@@ -362,7 +364,7 @@ parse_rule_list_t *vocab_build_gnf(const Common::Array<parse_tree_branch_t> &bra
ntrules_nr = _vocab_rule_list_length(ntlist);
if (verbose)
- sciprintf("Starting with %d rules\n", ntrules_nr);
+ con->DebugPrintf("Starting with %d rules\n", ntrules_nr);
new_tlist = tlist;
tlist = NULL;
@@ -391,25 +393,24 @@ parse_rule_list_t *vocab_build_gnf(const Common::Array<parse_tree_branch_t> &bra
termrules = _vocab_rule_list_length(new_new_tlist);
if (verbose)
- sciprintf("After iteration #%d: %d new term rules\n", ++iterations, termrules);
+ con->DebugPrintf("After iteration #%d: %d new term rules\n", ++iterations, termrules);
} while (termrules && (iterations < 30));
- vocab_free_rule_list(ntlist);
+ freeRuleList(ntlist);
if (verbose) {
- sciprintf("\nGNF rules:\n");
+ con->DebugPrintf("\nGNF rules:\n");
vocab_print_rule_list(tlist);
+ con->DebugPrintf("%d allocd rules\n", getAllocatedRulesCount());
+ con->DebugPrintf("Freeing rule list...\n");
+ freeRuleList(tlist);
+ return NULL;
}
return tlist;
}
-int vocab_build_parse_tree(parse_tree_node_t *nodes, const ResultWordList &words,
- const parse_tree_branch_t &branch0, parse_rule_list_t *rules) {
- return vocab_gnf_parse(nodes, words, branch0, rules, 0);
-}
-
static int _vbpt_pareno(parse_tree_node_t *nodes, int *pos, int base) {
// Opens parentheses
nodes[base].content.branches[0] = (*pos) + 1;
@@ -475,10 +476,10 @@ static int _vbpt_write_subexpression(parse_tree_node_t *nodes, int *pos, parse_r
return rulepos;
}
-int vocab_gnf_parse(parse_tree_node_t *nodes, const ResultWordList &words,
- const parse_tree_branch_t &branch0, parse_rule_list_t *tlist, int verbose) {
+int Vocabulary::parseGNF(parse_tree_node_t *nodes, const ResultWordList &words, bool verbose) {
+ Sci::Console *con = ((SciEngine *)g_engine)->_console;
// Get the start rules:
- parse_rule_list_t *work = _vocab_clone_rule_list_by_id(tlist, branch0.data[1]);
+ parse_rule_list_t *work = _vocab_clone_rule_list_by_id(_parserRules, _parserBranches[0].data[1]);
parse_rule_list_t *results = NULL;
int word = 0;
const int words_nr = words.size();
@@ -490,7 +491,7 @@ int vocab_gnf_parse(parse_tree_node_t *nodes, const ResultWordList &words,
parse_rule_list_t *seeker, *subseeker;
if (verbose)
- sciprintf("Adding word %d...\n", word);
+ con->DebugPrintf("Adding word %d...\n", word);
seeker = work;
while (seeker) {
@@ -501,13 +502,13 @@ int vocab_gnf_parse(parse_tree_node_t *nodes, const ResultWordList &words,
}
if (reduced_rules == NULL) {
- vocab_free_rule_list(work);
+ freeRuleList(work);
if (verbose)
- sciprintf("No results.\n");
+ con->DebugPrintf("No results.\n");
return 1;
}
- vocab_free_rule_list(work);
+ freeRuleList(work);
if (word + 1 < words_nr) {
seeker = reduced_rules;
@@ -516,7 +517,7 @@ int vocab_gnf_parse(parse_tree_node_t *nodes, const ResultWordList &words,
if (seeker->rule->specials_nr) {
int my_id = seeker->rule->data[seeker->rule->first_special];
- subseeker = tlist;
+ subseeker = _parserRules;
while (subseeker) {
if (subseeker->rule->id == my_id)
new_work = _vocab_add_rule(new_work, _vinsert(seeker->rule, subseeker->rule));
@@ -527,16 +528,16 @@ int vocab_gnf_parse(parse_tree_node_t *nodes, const ResultWordList &words,
seeker = seeker->next;
}
- vocab_free_rule_list(reduced_rules);
+ freeRuleList(reduced_rules);
} else // last word
new_work = reduced_rules;
work = new_work;
if (verbose)
- sciprintf("Now at %d candidates\n", _vocab_rule_list_length(work));
+ con->DebugPrintf("Now at %d candidates\n", _vocab_rule_list_length(work));
if (work == NULL) {
if (verbose)
- sciprintf("No results.\n");
+ con->DebugPrintf("No results.\n");
return 1;
}
}
@@ -544,9 +545,9 @@ int vocab_gnf_parse(parse_tree_node_t *nodes, const ResultWordList &words,
results = work;
if (verbose) {
- sciprintf("All results (excluding the surrounding '(141 %03x' and ')'):\n", branch0.id);
+ con->DebugPrintf("All results (excluding the surrounding '(141 %03x' and ')'):\n", _parserBranches[0].id);
vocab_print_rule_list(results);
- sciprintf("\n");
+ con->DebugPrintf("\n");
}
// now use the first result
@@ -566,12 +567,12 @@ int vocab_gnf_parse(parse_tree_node_t *nodes, const ResultWordList &words,
pos = 2;
- temp = _vbpt_append(nodes, &pos, 2, branch0.id);
+ temp = _vbpt_append(nodes, &pos, 2, _parserBranches[0].id);
//_vbpt_write_subexpression(nodes, &pos, results[_vocab_rule_list_length(results)].rule, 0, temp);
_vbpt_write_subexpression(nodes, &pos, results->rule, 0, temp);
}
- vocab_free_rule_list(results);
+ freeRuleList(results);
return 0;
}
diff --git a/engines/sci/engine/kernel.cpp b/engines/sci/engine/kernel.cpp
index 87b3a76141..b205a706e1 100644
--- a/engines/sci/engine/kernel.cpp
+++ b/engines/sci/engine/kernel.cpp
@@ -33,6 +33,270 @@
namespace Sci {
+/** The string used to identify the "unknown" SCI0 function for each game */
+#define SCRIPT_UNKNOWN_FUNCTION_STRING "[Unknown]"
+
+// Default kernel name table
+#define SCI0_KNAMES_WELL_DEFINED 0x6e
+#define SCI0_KNAMES_DEFAULT_ENTRIES_NR 0x72
+#define SCI1_KNAMES_DEFAULT_ENTRIES_NR 0x89
+
+static const char *sci0_default_knames[SCI0_KNAMES_DEFAULT_ENTRIES_NR] = {
+ /*0x00*/ "Load",
+ /*0x01*/ "UnLoad",
+ /*0x02*/ "ScriptID",
+ /*0x03*/ "DisposeScript",
+ /*0x04*/ "Clone",
+ /*0x05*/ "DisposeClone",
+ /*0x06*/ "IsObject",
+ /*0x07*/ "RespondsTo",
+ /*0x08*/ "DrawPic",
+ /*0x09*/ "Show",
+ /*0x0a*/ "PicNotValid",
+ /*0x0b*/ "Animate",
+ /*0x0c*/ "SetNowSeen",
+ /*0x0d*/ "NumLoops",
+ /*0x0e*/ "NumCels",
+ /*0x0f*/ "CelWide",
+ /*0x10*/ "CelHigh",
+ /*0x11*/ "DrawCel",
+ /*0x12*/ "AddToPic",
+ /*0x13*/ "NewWindow",
+ /*0x14*/ "GetPort",
+ /*0x15*/ "SetPort",
+ /*0x16*/ "DisposeWindow",
+ /*0x17*/ "DrawControl",
+ /*0x18*/ "HiliteControl",
+ /*0x19*/ "EditControl",
+ /*0x1a*/ "TextSize",
+ /*0x1b*/ "Display",
+ /*0x1c*/ "GetEvent",
+ /*0x1d*/ "GlobalToLocal",
+ /*0x1e*/ "LocalToGlobal",
+ /*0x1f*/ "MapKeyToDir",
+ /*0x20*/ "DrawMenuBar",
+ /*0x21*/ "MenuSelect",
+ /*0x22*/ "AddMenu",
+ /*0x23*/ "DrawStatus",
+ /*0x24*/ "Parse",
+ /*0x25*/ "Said",
+ /*0x26*/ "SetSynonyms",
+ /*0x27*/ "HaveMouse",
+ /*0x28*/ "SetCursor",
+ /*0x29*/ "FOpen",
+ /*0x2a*/ "FPuts",
+ /*0x2b*/ "FGets",
+ /*0x2c*/ "FClose",
+ /*0x2d*/ "SaveGame",
+ /*0x2e*/ "RestoreGame",
+ /*0x2f*/ "RestartGame",
+ /*0x30*/ "GameIsRestarting",
+ /*0x31*/ "DoSound",
+ /*0x32*/ "NewList",
+ /*0x33*/ "DisposeList",
+ /*0x34*/ "NewNode",
+ /*0x35*/ "FirstNode",
+ /*0x36*/ "LastNode",
+ /*0x37*/ "EmptyList",
+ /*0x38*/ "NextNode",
+ /*0x39*/ "PrevNode",
+ /*0x3a*/ "NodeValue",
+ /*0x3b*/ "AddAfter",
+ /*0x3c*/ "AddToFront",
+ /*0x3d*/ "AddToEnd",
+ /*0x3e*/ "FindKey",
+ /*0x3f*/ "DeleteKey",
+ /*0x40*/ "Random",
+ /*0x41*/ "Abs",
+ /*0x42*/ "Sqrt",
+ /*0x43*/ "GetAngle",
+ /*0x44*/ "GetDistance",
+ /*0x45*/ "Wait",
+ /*0x46*/ "GetTime",
+ /*0x47*/ "StrEnd",
+ /*0x48*/ "StrCat",
+ /*0x49*/ "StrCmp",
+ /*0x4a*/ "StrLen",
+ /*0x4b*/ "StrCpy",
+ /*0x4c*/ "Format",
+ /*0x4d*/ "GetFarText",
+ /*0x4e*/ "ReadNumber",
+ /*0x4f*/ "BaseSetter",
+ /*0x50*/ "DirLoop",
+ /*0x51*/ "CanBeHere",
+ /*0x52*/ "OnControl",
+ /*0x53*/ "InitBresen",
+ /*0x54*/ "DoBresen",
+ /*0x55*/ "DoAvoider",
+ /*0x56*/ "SetJump",
+ /*0x57*/ "SetDebug",
+ /*0x58*/ "InspectObj",
+ /*0x59*/ "ShowSends",
+ /*0x5a*/ "ShowObjs",
+ /*0x5b*/ "ShowFree",
+ /*0x5c*/ "MemoryInfo",
+ /*0x5d*/ "StackUsage",
+ /*0x5e*/ "Profiler",
+ /*0x5f*/ "GetMenu",
+ /*0x60*/ "SetMenu",
+ /*0x61*/ "GetSaveFiles",
+ /*0x62*/ "GetCWD",
+ /*0x63*/ "CheckFreeSpace",
+ /*0x64*/ "ValidPath",
+ /*0x65*/ "CoordPri",
+ /*0x66*/ "StrAt",
+ /*0x67*/ "DeviceInfo",
+ /*0x68*/ "GetSaveDir",
+ /*0x69*/ "CheckSaveGame",
+ /*0x6a*/ "ShakeScreen",
+ /*0x6b*/ "FlushResources",
+ /*0x6c*/ "SinMult",
+ /*0x6d*/ "CosMult",
+ /*0x6e*/ "SinDiv",
+ /*0x6f*/ "CosDiv",
+ /*0x70*/ "Graph",
+ /*0x71*/ SCRIPT_UNKNOWN_FUNCTION_STRING
+};
+
+static const char *sci1_default_knames[SCI1_KNAMES_DEFAULT_ENTRIES_NR] = {
+ /*0x00*/ "Load",
+ /*0x01*/ "UnLoad",
+ /*0x02*/ "ScriptID",
+ /*0x03*/ "DisposeScript",
+ /*0x04*/ "Clone",
+ /*0x05*/ "DisposeClone",
+ /*0x06*/ "IsObject",
+ /*0x07*/ "RespondsTo",
+ /*0x08*/ "DrawPic",
+ /*0x09*/ "Show",
+ /*0x0a*/ "PicNotValid",
+ /*0x0b*/ "Animate",
+ /*0x0c*/ "SetNowSeen",
+ /*0x0d*/ "NumLoops",
+ /*0x0e*/ "NumCels",
+ /*0x0f*/ "CelWide",
+ /*0x10*/ "CelHigh",
+ /*0x11*/ "DrawCel",
+ /*0x12*/ "AddToPic",
+ /*0x13*/ "NewWindow",
+ /*0x14*/ "GetPort",
+ /*0x15*/ "SetPort",
+ /*0x16*/ "DisposeWindow",
+ /*0x17*/ "DrawControl",
+ /*0x18*/ "HiliteControl",
+ /*0x19*/ "EditControl",
+ /*0x1a*/ "TextSize",
+ /*0x1b*/ "Display",
+ /*0x1c*/ "GetEvent",
+ /*0x1d*/ "GlobalToLocal",
+ /*0x1e*/ "LocalToGlobal",
+ /*0x1f*/ "MapKeyToDir",
+ /*0x20*/ "DrawMenuBar",
+ /*0x21*/ "MenuSelect",
+ /*0x22*/ "AddMenu",
+ /*0x23*/ "DrawStatus",
+ /*0x24*/ "Parse",
+ /*0x25*/ "Said",
+ /*0x26*/ "SetSynonyms",
+ /*0x27*/ "HaveMouse",
+ /*0x28*/ "SetCursor",
+ /*0x29*/ "SaveGame",
+ /*0x2a*/ "RestoreGame",
+ /*0x2b*/ "RestartGame",
+ /*0x2c*/ "GameIsRestarting",
+ /*0x2d*/ "DoSound",
+ /*0x2e*/ "NewList",
+ /*0x2f*/ "DisposeList",
+ /*0x30*/ "NewNode",
+ /*0x31*/ "FirstNode",
+ /*0x32*/ "LastNode",
+ /*0x33*/ "EmptyList",
+ /*0x34*/ "NextNode",
+ /*0x35*/ "PrevNode",
+ /*0x36*/ "NodeValue",
+ /*0x37*/ "AddAfter",
+ /*0x38*/ "AddToFront",
+ /*0x39*/ "AddToEnd",
+ /*0x3a*/ "FindKey",
+ /*0x3b*/ "DeleteKey",
+ /*0x3c*/ "Random",
+ /*0x3d*/ "Abs",
+ /*0x3e*/ "Sqrt",
+ /*0x3f*/ "GetAngle",
+ /*0x40*/ "GetDistance",
+ /*0x41*/ "Wait",
+ /*0x42*/ "GetTime",
+ /*0x43*/ "StrEnd",
+ /*0x44*/ "StrCat",
+ /*0x45*/ "StrCmp",
+ /*0x46*/ "StrLen",
+ /*0x47*/ "StrCpy",
+ /*0x48*/ "Format",
+ /*0x49*/ "GetFarText",
+ /*0x4a*/ "ReadNumber",
+ /*0x4b*/ "BaseSetter",
+ /*0x4c*/ "DirLoop",
+ /*0x4d*/ "CanBeHere",
+ /*0x4e*/ "OnControl",
+ /*0x4f*/ "InitBresen",
+ /*0x50*/ "DoBresen",
+ /*0x51*/ "Platform",
+ /*0x52*/ "SetJump",
+ /*0x53*/ "SetDebug",
+ /*0x54*/ "InspectObj",
+ /*0x55*/ "ShowSends",
+ /*0x56*/ "ShowObjs",
+ /*0x57*/ "ShowFree",
+ /*0x58*/ "MemoryInfo",
+ /*0x59*/ "StackUsage",
+ /*0x5a*/ "Profiler",
+ /*0x5b*/ "GetMenu",
+ /*0x5c*/ "SetMenu",
+ /*0x5d*/ "GetSaveFiles",
+ /*0x5e*/ "GetCWD",
+ /*0x5f*/ "CheckFreeSpace",
+ /*0x60*/ "ValidPath",
+ /*0x61*/ "CoordPri",
+ /*0x62*/ "StrAt",
+ /*0x63*/ "DeviceInfo",
+ /*0x64*/ "GetSaveDir",
+ /*0x65*/ "CheckSaveGame",
+ /*0x66*/ "ShakeScreen",
+ /*0x67*/ "FlushResources",
+ /*0x68*/ "SinMult",
+ /*0x69*/ "CosMult",
+ /*0x6a*/ "SinDiv",
+ /*0x6b*/ "CosDiv",
+ /*0x6c*/ "Graph",
+ /*0x6d*/ "Joystick",
+ /*0x6e*/ "ShiftScreen",
+ /*0x6f*/ "Palette",
+ /*0x70*/ "MemorySegment",
+ /*0x71*/ "MoveCursor",
+ /*0x72*/ "Memory",
+ /*0x73*/ "ListOps",
+ /*0x74*/ "FileIO",
+ /*0x75*/ "DoAudio",
+ /*0x76*/ "DoSync",
+ /*0x77*/ "AvoidPath",
+ /*0x78*/ "Sort",
+ /*0x79*/ "ATan",
+ /*0x7a*/ "Lock",
+ /*0x7b*/ "StrSplit",
+ /*0x7c*/ "Message",
+ /*0x7d*/ "IsItSkip",
+ /*0x7e*/ "MergePoly",
+ /*0x7f*/ "ResCheck",
+ /*0x80*/ "AssertPalette",
+ /*0x81*/ "TextColors",
+ /*0x82*/ "TextFonts",
+ /*0x83*/ "Record",
+ /*0x84*/ "PlayBack",
+ /*0x85*/ "ShowMovie",
+ /*0x86*/ "SetVideoMode",
+ /*0x87*/ "SetQuitStr",
+ /*0x88*/ "DbugStr"
+};
enum KernelFunctionType {
KF_NEW = 1,
@@ -556,4 +820,133 @@ reg_t *kernel_dereference_reg_pointer(EngineState *s, reg_t pointer, int entries
return (reg_t*)_kernel_dereference_pointer(s, pointer, entries, sizeof(reg_t));
}
+// Alternative kernel func names retriever. Required for KQ1/SCI (at least).
+static void _vocab_get_knames0alt(const Resource *r, Common::StringList &names) {
+ uint idx = 0;
+
+ while (idx < r->size) {
+ Common::String tmp((const char *)r->data + idx);
+ names.push_back(tmp);
+ idx += tmp.size() + 1;
+ }
+
+ // The mystery kernel function- one in each SCI0 package
+ names.push_back(SCRIPT_UNKNOWN_FUNCTION_STRING);
+}
+
+static void vocab_get_knames0(ResourceManager *resmgr, Common::StringList &names) {
+ int count, i, index = 2, empty_to_add = 1;
+ Resource *r = resmgr->findResource(kResourceTypeVocab, VOCAB_RESOURCE_KNAMES, 0);
+
+ if (!r) { // No kernel name table found? Fall back to default table
+ names.resize(SCI0_KNAMES_DEFAULT_ENTRIES_NR);
+ for (i = 0; i < SCI0_KNAMES_DEFAULT_ENTRIES_NR; i++)
+ names[i] = sci0_default_knames[i];
+ return;
+ }
+
+ count = READ_LE_UINT16(r->data);
+
+ if (count > 1023) {
+ _vocab_get_knames0alt(r, names);
+ return;
+ }
+
+ if (count < SCI0_KNAMES_WELL_DEFINED) {
+ empty_to_add = SCI0_KNAMES_WELL_DEFINED - count;
+ sciprintf("Less than %d kernel functions; adding %d\n", SCI0_KNAMES_WELL_DEFINED, empty_to_add);
+ }
+
+ names.resize(count + 1 + empty_to_add);
+
+ for (i = 0; i < count; i++) {
+ int offset = READ_LE_UINT16(r->data + index);
+ int len = READ_LE_UINT16(r->data + offset);
+ //fprintf(stderr,"Getting name %d of %d...\n", i, count);
+ index += 2;
+ names[i] = Common::String((const char *)r->data + offset + 2, len);
+ }
+
+ for (i = 0; i < empty_to_add; i++) {
+ names[count + i] = SCRIPT_UNKNOWN_FUNCTION_STRING;
+ }
+}
+
+static void vocab_get_knames1(ResourceManager *resmgr, Common::StringList &names) {
+ // vocab.999/999.voc is notoriously unreliable in SCI1 games, and should not be used
+ // We hardcode the default SCI1 kernel names here (i.e. the ones inside the "special"
+ // 999.voc file from FreeSCI). All SCI1 games seem to be working with this change, but
+ // if any SCI1 game has different kernel vocabulary names, it might not work. It seems
+ // that all SCI1 games use the same kernel vocabulary names though, so this seems to be
+ // a safe change. If there's any SCI1 game with different kernel vocabulary names, we can
+ // add special flags to it to our detector
+
+ names.resize(SCI1_KNAMES_DEFAULT_ENTRIES_NR);
+ for (int i = 0; i < SCI1_KNAMES_DEFAULT_ENTRIES_NR; i++)
+ names[i] = sci1_default_knames[i];
+}
+
+#ifdef ENABLE_SCI32
+static void vocab_get_knames11(ResourceManager *resmgr, Common::StringList &names) {
+/*
+ 999.voc format for SCI1.1 games:
+ [b] # of kernel functions
+ [w] unknown
+ [offset to function name info]
+ ...
+ {[w name-len][function name]}
+ ...
+*/
+ //unsigned int size = 64, pos = 3;
+ int len;
+ Resource *r = resmgr->findResource(kResourceTypeVocab, VOCAB_RESOURCE_KNAMES, 0);
+ if(r == NULL) // failed to open vocab.999 (happens with SCI1 demos)
+ return; // FIXME: should return a default table for this engine
+ const byte nCnt = *r->data;
+
+ names.resize(nCnt);
+ for (int i = 0; i < nCnt; i++) {
+ int off = READ_LE_UINT16(r->data + 2 * i + 2);
+ len = READ_LE_UINT16(r->data + off);
+ names[i] = Common::String((char *)r->data + off + 2, len);
+ }
+}
+#endif
+
+bool Vocabulary::getKernelNames() {
+ _kernelNames.clear();
+
+ switch (_resmgr->_sciVersion) {
+ case SCI_VERSION_0:
+ case SCI_VERSION_01:
+ vocab_get_knames0(_resmgr, _kernelNames);
+ break;
+ case SCI_VERSION_01_VGA:
+ case SCI_VERSION_01_VGA_ODD:
+ // HACK: KQ5 needs the SCI1 default vocabulary names to work correctly.
+ // Having more vocabulary names (like in SCI1) doesn't seem to have any
+ // ill effects, other than resulting in unmapped functions towards the
+ // end, which are never used by the game interpreter anyway
+ // return vocab_get_knames0(resmgr, count);
+ case SCI_VERSION_1_EARLY:
+ case SCI_VERSION_1_LATE:
+ vocab_get_knames1(_resmgr, _kernelNames);
+ break;
+ case SCI_VERSION_1_1:
+ vocab_get_knames1(_resmgr, _kernelNames);
+ // KQ6CD calls unimplemented function 0x26
+ _kernelNames[0x26] = "Dummy";
+ break;
+#ifdef ENABLE_SCI32
+ case SCI_VERSION_32:
+ vocab_get_knames11(_resmgr, _kernelNames);
+#endif
+ break;
+ default:
+ break;
+ }
+
+ return true;
+}
+
} // End of namespace Sci
diff --git a/engines/sci/engine/kstring.cpp b/engines/sci/engine/kstring.cpp
index 1f61b0ecb9..1bc69fccbf 100644
--- a/engines/sci/engine/kstring.cpp
+++ b/engines/sci/engine/kstring.cpp
@@ -95,7 +95,7 @@ reg_t kSaid(EngineState *s, int funct_nr, int argc, reg_t *argv) {
#ifdef DEBUG_PARSER
debugC(2, kDebugLevelParser, "Said block:", 0);
- vocab_decypher_said_block(s, said_block);
+ s->_vocabulary->decypherSaidBlock(said_block);
#endif
if (s->parser_event.isNull() || (GET_SEL32V(s->parser_event, claimed))) {
@@ -221,8 +221,7 @@ reg_t kParse(EngineState *s, int funct_nr, int argc, reg_t *argv) {
debugC(2, kDebugLevelParser, " Type[%04x] Group[%04x]\n", i->_class, i->_group);
#endif
- if (vocab_build_parse_tree(s->parser_nodes, words, s->_vocabulary->_parserBranches[0],
- s->parser_rules))
+ if (s->_vocabulary->parseGNF(s->parser_nodes, words))
syntax_fail = 1; /* Building a tree failed */
if (syntax_fail) {
diff --git a/engines/sci/engine/said.cpp b/engines/sci/engine/said.cpp
index a03c829357..964e67d230 100644
--- a/engines/sci/engine/said.cpp
+++ b/engines/sci/engine/said.cpp
@@ -2448,7 +2448,7 @@ int said(EngineState *s, byte *spec, int verbose) {
if (s->parser_valid) {
if (said_parse_spec(s, spec)) {
sciprintf("Offending spec was: ");
- vocab_decypher_said_block(s, spec);
+ s->_vocabulary->decypherSaidBlock(spec);
return SAID_NO_MATCH;
}
diff --git a/engines/sci/engine/said.y b/engines/sci/engine/said.y
index ecea28d848..10906d94ef 100644
--- a/engines/sci/engine/said.y
+++ b/engines/sci/engine/said.y
@@ -804,7 +804,7 @@ int said(EngineState *s, byte *spec, int verbose) {
if (s->parser_valid) {
if (said_parse_spec(s, spec)) {
sciprintf("Offending spec was: ");
- vocab_decypher_said_block(s, spec);
+ s->_vocabulary->decypherSaidBlock(spec);
return SAID_NO_MATCH;
}
diff --git a/engines/sci/engine/savegame.cpp b/engines/sci/engine/savegame.cpp
index fe6f0f1376..a25915622b 100644
--- a/engines/sci/engine/savegame.cpp
+++ b/engines/sci/engine/savegame.cpp
@@ -823,10 +823,7 @@ EngineState *gamestate_restore(EngineState *s, Common::SeekableReadStream *fh) {
retval->game_start_time = g_system->getMillis() - retval->game_time * 1000;
// static parser information:
- retval->parser_rules = s->parser_rules;
- retval->_vocabulary->_parserWords = s->_vocabulary->_parserWords;
- retval->_vocabulary->_parserSuffixes = s->_vocabulary->_parserSuffixes;
- retval->_vocabulary->_parserBranches = s->_vocabulary->_parserBranches;
+ retval->_vocabulary->copyParserListsFrom(s->_vocabulary);
// static VM/Kernel information:
retval->_vocabulary->_selectorNames = s->_vocabulary->_selectorNames;
diff --git a/engines/sci/engine/scriptdebug.cpp b/engines/sci/engine/scriptdebug.cpp
index fa6a1e960b..68808ee14b 100644
--- a/engines/sci/engine/scriptdebug.cpp
+++ b/engines/sci/engine/scriptdebug.cpp
@@ -659,7 +659,7 @@ int c_parse(EngineState *s, const Common::Array<cmd_param_t> &cmdParams) {
for (ResultWordList::const_iterator i = words.begin(); i != words.end(); ++i)
sciprintf(" Type[%04x] Group[%04x]\n", i->_class, i->_group);
- if (vocab_gnf_parse(s->parser_nodes, words, s->_vocabulary->_parserBranches[0], s->parser_rules, 1))
+ if (s->_vocabulary->parseGNF(s->parser_nodes, words, true))
syntax_fail = 1; // Building a tree failed
if (syntax_fail)
diff --git a/engines/sci/engine/state.cpp b/engines/sci/engine/state.cpp
index 68b706cfb4..6ade204930 100644
--- a/engines/sci/engine/state.cpp
+++ b/engines/sci/engine/state.cpp
@@ -111,7 +111,6 @@ EngineState::EngineState() : _dirseeker(this) {
sys_strings = 0;
string_frag_segment = 0;
- parser_rules = 0;
memset(parser_nodes, 0, sizeof(parser_nodes));
parser_valid = 0;
diff --git a/engines/sci/engine/state.h b/engines/sci/engine/state.h
index ee22a9e31d..79b753b1be 100644
--- a/engines/sci/engine/state.h
+++ b/engines/sci/engine/state.h
@@ -226,7 +226,6 @@ public:
SegmentId string_frag_segment;
/* Parser data: */
- parse_rule_list_t *parser_rules; /**< GNF rules used in the parser algorithm */
parse_tree_node_t parser_nodes[VOCAB_TREE_NODES]; /**< The parse tree */
int parser_valid; /**< If something has been correctly parsed */
diff --git a/engines/sci/vocabulary.cpp b/engines/sci/vocabulary.cpp
index 6e1d26e4ac..6f3a13b6de 100644
--- a/engines/sci/vocabulary.cpp
+++ b/engines/sci/vocabulary.cpp
@@ -29,274 +29,10 @@
#include "sci/resource.h"
#include "sci/engine/state.h"
#include "sci/engine/kernel.h"
+#include "sci/console.h"
namespace Sci {
-/** The string used to identify the "unknown" SCI0 function for each game */
-#define SCRIPT_UNKNOWN_FUNCTION_STRING "[Unknown]"
-
-// Default kernel name table
-#define SCI0_KNAMES_WELL_DEFINED 0x6e
-#define SCI0_KNAMES_DEFAULT_ENTRIES_NR 0x72
-#define SCI1_KNAMES_DEFAULT_ENTRIES_NR 0x89
-
-static const char *sci0_default_knames[SCI0_KNAMES_DEFAULT_ENTRIES_NR] = {
- /*0x00*/ "Load",
- /*0x01*/ "UnLoad",
- /*0x02*/ "ScriptID",
- /*0x03*/ "DisposeScript",
- /*0x04*/ "Clone",
- /*0x05*/ "DisposeClone",
- /*0x06*/ "IsObject",
- /*0x07*/ "RespondsTo",
- /*0x08*/ "DrawPic",
- /*0x09*/ "Show",
- /*0x0a*/ "PicNotValid",
- /*0x0b*/ "Animate",
- /*0x0c*/ "SetNowSeen",
- /*0x0d*/ "NumLoops",
- /*0x0e*/ "NumCels",
- /*0x0f*/ "CelWide",
- /*0x10*/ "CelHigh",
- /*0x11*/ "DrawCel",
- /*0x12*/ "AddToPic",
- /*0x13*/ "NewWindow",
- /*0x14*/ "GetPort",
- /*0x15*/ "SetPort",
- /*0x16*/ "DisposeWindow",
- /*0x17*/ "DrawControl",
- /*0x18*/ "HiliteControl",
- /*0x19*/ "EditControl",
- /*0x1a*/ "TextSize",
- /*0x1b*/ "Display",
- /*0x1c*/ "GetEvent",
- /*0x1d*/ "GlobalToLocal",
- /*0x1e*/ "LocalToGlobal",
- /*0x1f*/ "MapKeyToDir",
- /*0x20*/ "DrawMenuBar",
- /*0x21*/ "MenuSelect",
- /*0x22*/ "AddMenu",
- /*0x23*/ "DrawStatus",
- /*0x24*/ "Parse",
- /*0x25*/ "Said",
- /*0x26*/ "SetSynonyms",
- /*0x27*/ "HaveMouse",
- /*0x28*/ "SetCursor",
- /*0x29*/ "FOpen",
- /*0x2a*/ "FPuts",
- /*0x2b*/ "FGets",
- /*0x2c*/ "FClose",
- /*0x2d*/ "SaveGame",
- /*0x2e*/ "RestoreGame",
- /*0x2f*/ "RestartGame",
- /*0x30*/ "GameIsRestarting",
- /*0x31*/ "DoSound",
- /*0x32*/ "NewList",
- /*0x33*/ "DisposeList",
- /*0x34*/ "NewNode",
- /*0x35*/ "FirstNode",
- /*0x36*/ "LastNode",
- /*0x37*/ "EmptyList",
- /*0x38*/ "NextNode",
- /*0x39*/ "PrevNode",
- /*0x3a*/ "NodeValue",
- /*0x3b*/ "AddAfter",
- /*0x3c*/ "AddToFront",
- /*0x3d*/ "AddToEnd",
- /*0x3e*/ "FindKey",
- /*0x3f*/ "DeleteKey",
- /*0x40*/ "Random",
- /*0x41*/ "Abs",
- /*0x42*/ "Sqrt",
- /*0x43*/ "GetAngle",
- /*0x44*/ "GetDistance",
- /*0x45*/ "Wait",
- /*0x46*/ "GetTime",
- /*0x47*/ "StrEnd",
- /*0x48*/ "StrCat",
- /*0x49*/ "StrCmp",
- /*0x4a*/ "StrLen",
- /*0x4b*/ "StrCpy",
- /*0x4c*/ "Format",
- /*0x4d*/ "GetFarText",
- /*0x4e*/ "ReadNumber",
- /*0x4f*/ "BaseSetter",
- /*0x50*/ "DirLoop",
- /*0x51*/ "CanBeHere",
- /*0x52*/ "OnControl",
- /*0x53*/ "InitBresen",
- /*0x54*/ "DoBresen",
- /*0x55*/ "DoAvoider",
- /*0x56*/ "SetJump",
- /*0x57*/ "SetDebug",
- /*0x58*/ "InspectObj",
- /*0x59*/ "ShowSends",
- /*0x5a*/ "ShowObjs",
- /*0x5b*/ "ShowFree",
- /*0x5c*/ "MemoryInfo",
- /*0x5d*/ "StackUsage",
- /*0x5e*/ "Profiler",
- /*0x5f*/ "GetMenu",
- /*0x60*/ "SetMenu",
- /*0x61*/ "GetSaveFiles",
- /*0x62*/ "GetCWD",
- /*0x63*/ "CheckFreeSpace",
- /*0x64*/ "ValidPath",
- /*0x65*/ "CoordPri",
- /*0x66*/ "StrAt",
- /*0x67*/ "DeviceInfo",
- /*0x68*/ "GetSaveDir",
- /*0x69*/ "CheckSaveGame",
- /*0x6a*/ "ShakeScreen",
- /*0x6b*/ "FlushResources",
- /*0x6c*/ "SinMult",
- /*0x6d*/ "CosMult",
- /*0x6e*/ "SinDiv",
- /*0x6f*/ "CosDiv",
- /*0x70*/ "Graph",
- /*0x71*/ SCRIPT_UNKNOWN_FUNCTION_STRING
-};
-
-static const char *sci1_default_knames[SCI1_KNAMES_DEFAULT_ENTRIES_NR] = {
- /*0x00*/ "Load",
- /*0x01*/ "UnLoad",
- /*0x02*/ "ScriptID",
- /*0x03*/ "DisposeScript",
- /*0x04*/ "Clone",
- /*0x05*/ "DisposeClone",
- /*0x06*/ "IsObject",
- /*0x07*/ "RespondsTo",
- /*0x08*/ "DrawPic",
- /*0x09*/ "Show",
- /*0x0a*/ "PicNotValid",
- /*0x0b*/ "Animate",
- /*0x0c*/ "SetNowSeen",
- /*0x0d*/ "NumLoops",
- /*0x0e*/ "NumCels",
- /*0x0f*/ "CelWide",
- /*0x10*/ "CelHigh",
- /*0x11*/ "DrawCel",
- /*0x12*/ "AddToPic",
- /*0x13*/ "NewWindow",
- /*0x14*/ "GetPort",
- /*0x15*/ "SetPort",
- /*0x16*/ "DisposeWindow",
- /*0x17*/ "DrawControl",
- /*0x18*/ "HiliteControl",
- /*0x19*/ "EditControl",
- /*0x1a*/ "TextSize",
- /*0x1b*/ "Display",
- /*0x1c*/ "GetEvent",
- /*0x1d*/ "GlobalToLocal",
- /*0x1e*/ "LocalToGlobal",
- /*0x1f*/ "MapKeyToDir",
- /*0x20*/ "DrawMenuBar",
- /*0x21*/ "MenuSelect",
- /*0x22*/ "AddMenu",
- /*0x23*/ "DrawStatus",
- /*0x24*/ "Parse",
- /*0x25*/ "Said",
- /*0x26*/ "SetSynonyms",
- /*0x27*/ "HaveMouse",
- /*0x28*/ "SetCursor",
- /*0x29*/ "SaveGame",
- /*0x2a*/ "RestoreGame",
- /*0x2b*/ "RestartGame",
- /*0x2c*/ "GameIsRestarting",
- /*0x2d*/ "DoSound",
- /*0x2e*/ "NewList",
- /*0x2f*/ "DisposeList",
- /*0x30*/ "NewNode",
- /*0x31*/ "FirstNode",
- /*0x32*/ "LastNode",
- /*0x33*/ "EmptyList",
- /*0x34*/ "NextNode",
- /*0x35*/ "PrevNode",
- /*0x36*/ "NodeValue",
- /*0x37*/ "AddAfter",
- /*0x38*/ "AddToFront",
- /*0x39*/ "AddToEnd",
- /*0x3a*/ "FindKey",
- /*0x3b*/ "DeleteKey",
- /*0x3c*/ "Random",
- /*0x3d*/ "Abs",
- /*0x3e*/ "Sqrt",
- /*0x3f*/ "GetAngle",
- /*0x40*/ "GetDistance",
- /*0x41*/ "Wait",
- /*0x42*/ "GetTime",
- /*0x43*/ "StrEnd",
- /*0x44*/ "StrCat",
- /*0x45*/ "StrCmp",
- /*0x46*/ "StrLen",
- /*0x47*/ "StrCpy",
- /*0x48*/ "Format",
- /*0x49*/ "GetFarText",
- /*0x4a*/ "ReadNumber",
- /*0x4b*/ "BaseSetter",
- /*0x4c*/ "DirLoop",
- /*0x4d*/ "CanBeHere",
- /*0x4e*/ "OnControl",
- /*0x4f*/ "InitBresen",
- /*0x50*/ "DoBresen",
- /*0x51*/ "Platform",
- /*0x52*/ "SetJump",
- /*0x53*/ "SetDebug",
- /*0x54*/ "InspectObj",
- /*0x55*/ "ShowSends",
- /*0x56*/ "ShowObjs",
- /*0x57*/ "ShowFree",
- /*0x58*/ "MemoryInfo",
- /*0x59*/ "StackUsage",
- /*0x5a*/ "Profiler",
- /*0x5b*/ "GetMenu",
- /*0x5c*/ "SetMenu",
- /*0x5d*/ "GetSaveFiles",
- /*0x5e*/ "GetCWD",
- /*0x5f*/ "CheckFreeSpace",
- /*0x60*/ "ValidPath",
- /*0x61*/ "CoordPri",
- /*0x62*/ "StrAt",
- /*0x63*/ "DeviceInfo",
- /*0x64*/ "GetSaveDir",
- /*0x65*/ "CheckSaveGame",
- /*0x66*/ "ShakeScreen",
- /*0x67*/ "FlushResources",
- /*0x68*/ "SinMult",
- /*0x69*/ "CosMult",
- /*0x6a*/ "SinDiv",
- /*0x6b*/ "CosDiv",
- /*0x6c*/ "Graph",
- /*0x6d*/ "Joystick",
- /*0x6e*/ "ShiftScreen",
- /*0x6f*/ "Palette",
- /*0x70*/ "MemorySegment",
- /*0x71*/ "MoveCursor",
- /*0x72*/ "Memory",
- /*0x73*/ "ListOps",
- /*0x74*/ "FileIO",
- /*0x75*/ "DoAudio",
- /*0x76*/ "DoSync",
- /*0x77*/ "AvoidPath",
- /*0x78*/ "Sort",
- /*0x79*/ "ATan",
- /*0x7a*/ "Lock",
- /*0x7b*/ "StrSplit",
- /*0x7c*/ "Message",
- /*0x7d*/ "IsItSkip",
- /*0x7e*/ "MergePoly",
- /*0x7f*/ "ResCheck",
- /*0x80*/ "AssertPalette",
- /*0x81*/ "TextColors",
- /*0x82*/ "TextFonts",
- /*0x83*/ "Record",
- /*0x84*/ "PlayBack",
- /*0x85*/ "ShowMovie",
- /*0x86*/ "SetVideoMode",
- /*0x87*/ "SetQuitStr",
- /*0x88*/ "DbugStr"
-};
-
#if 0
/**
@@ -349,9 +85,9 @@ int vocab_get_class_count(ResourceManager *resmgr) {
#endif
-Vocabulary::Vocabulary(EngineState *s) : _resmgr(s->resmgr), _isOldSci0(s->flags & GF_SCI0_OLD) {
- s->parser_rules = NULL;
- _vocabVersion = 0;
+Vocabulary::Vocabulary(ResourceManager *resmgr, bool isOldSci0) : _resmgr(resmgr), _isOldSci0(isOldSci0) {
+ _parserRules = NULL;
+ _vocabVersion = kVocabularySCI0;
memset(&_selectorMap, 0, sizeof(_selectorMap)); // FIXME: Remove this once/if we C++ify selector_map_t
debug(2, "Initializing vocabulary");
@@ -360,10 +96,10 @@ Vocabulary::Vocabulary(EngineState *s) : _resmgr(s->resmgr), _isOldSci0(s->flags
getSuffixes();
if (getBranches())
// Now build a GNF grammar out of this
- s->parser_rules = vocab_build_gnf(_parserBranches, 0);
+ _parserRules = buildGNF();
} else {
debug(2, "Assuming that this game does not use a parser.");
- s->parser_rules = NULL;
+ _parserRules = NULL;
}
getOpcodes();
@@ -379,6 +115,7 @@ Vocabulary::Vocabulary(EngineState *s) : _resmgr(s->resmgr), _isOldSci0(s->flags
}
Vocabulary::~Vocabulary() {
+ freeRuleList(_parserRules);
_parserWords.clear();
_selectorNames.clear();
_opcodes.clear();
@@ -453,7 +190,7 @@ bool Vocabulary::getParserWords() {
if (!resource) {
warning("SCI0: Could not find a main vocabulary, trying SCI01");
resource = _resmgr->findResource(kResourceTypeVocab, VOCAB_RESOURCE_SCI1_MAIN_VOCAB, 0);
- _vocabVersion = 1;
+ _vocabVersion = kVocabularySCI1;
}
if (!resource) {
@@ -462,7 +199,7 @@ bool Vocabulary::getParserWords() {
}
unsigned int seeker;
- if (_vocabVersion == 1)
+ if (_vocabVersion == kVocabularySCI1)
seeker = 255 * 2; // vocab.900 starts with 255 16-bit pointers which we don't use
else
seeker = 26 * 2; // vocab.000 starts with 26 16-bit pointers which we don't use
@@ -480,7 +217,7 @@ bool Vocabulary::getParserWords() {
currentwordpos = resource->data[seeker++]; // Parts of previous words may be re-used
- if (_vocabVersion == 1) {
+ if (_vocabVersion == kVocabularySCI1) {
c = 1;
while (seeker < resource->size && currentwordpos < 255 && c) {
c = resource->data[seeker++];
@@ -530,7 +267,7 @@ bool Vocabulary::getSuffixes() {
// Determine if we can find a SCI1 suffix vocabulary first
Resource* resource = NULL;
- if (_vocabVersion == 0)
+ if (_vocabVersion == kVocabularySCI0)
resource = _resmgr->findResource(kResourceTypeVocab, VOCAB_RESOURCE_SCI0_SUFFIX_VOCAB, 1);
else
resource = _resmgr->findResource(kResourceTypeVocab, VOCAB_RESOURCE_SCI1_SUFFIX_VOCAB, 1);
@@ -569,7 +306,7 @@ bool Vocabulary::getSuffixes() {
void Vocabulary::freeSuffixes() {
Resource* resource = NULL;
- if (_vocabVersion == 0)
+ if (_vocabVersion == kVocabularySCI0)
resource = _resmgr->findResource(kResourceTypeVocab, VOCAB_RESOURCE_SCI0_SUFFIX_VOCAB, 0);
else
resource = _resmgr->findResource(kResourceTypeVocab, VOCAB_RESOURCE_SCI1_SUFFIX_VOCAB, 0);
@@ -583,7 +320,7 @@ void Vocabulary::freeSuffixes() {
bool Vocabulary::getBranches() {
Resource *resource = NULL;
- if (_vocabVersion == 0)
+ if (_vocabVersion == kVocabularySCI0)
resource = _resmgr->findResource(kResourceTypeVocab, VOCAB_RESOURCE_SCI0_PARSE_TREE_BRANCHES, 0);
else
resource = _resmgr->findResource(kResourceTypeVocab, VOCAB_RESOURCE_SCI1_PARSE_TREE_BRANCHES, 0);
@@ -676,7 +413,7 @@ ResultWord Vocabulary::lookupWord(const char *word, int word_len) {
return retval;
}
-void vocab_decypher_said_block(EngineState *s, byte *addr) {
+void Vocabulary::decypherSaidBlock(byte *addr) {
int nextitem;
do {
@@ -684,7 +421,7 @@ void vocab_decypher_said_block(EngineState *s, byte *addr) {
if (nextitem < 0xf0) {
nextitem = nextitem << 8 | *addr++;
- sciprintf(" %s[%03x]", s->_vocabulary->getAnyWordFromGroup(nextitem), nextitem);
+ sciprintf(" %s[%03x]", getAnyWordFromGroup(nextitem), nextitem);
nextitem = 42; // Make sure that group 0xff doesn't abort
} else switch (nextitem) {
@@ -769,6 +506,48 @@ bool Vocabulary::tokenizeString(ResultWordList &retval, const char *sentence, ch
return true;
}
+void Vocabulary::printSuffixes() {
+ char word_buf[256], alt_buf[256];
+ Sci::Console *con = ((SciEngine *)g_engine)->_console;
+
+ int i = 0;
+ for (SuffixList::const_iterator suf = _parserSuffixes.begin(); suf != _parserSuffixes.end(); ++suf) {
+ strncpy(word_buf, suf->word_suffix, suf->word_suffix_length);
+ word_buf[suf->word_suffix_length] = 0;
+ strncpy(alt_buf, suf->alt_suffix, suf->alt_suffix_length);
+ alt_buf[suf->alt_suffix_length] = 0;
+
+ con->DebugPrintf("%4d: (%03x) -%12s => -%12s (%03x)\n", i, suf->class_mask, word_buf, alt_buf, suf->result_class);
+ ++i;
+ }
+}
+
+void Vocabulary::printParserWords() {
+ Sci::Console *con = ((SciEngine *)g_engine)->_console;
+
+ int j = 0;
+ for (WordMap::iterator i = _parserWords.begin(); i != _parserWords.end(); ++i) {
+ con->DebugPrintf("%4d: %03x [%03x] %20s |", j, i->_value._class, i->_value._group, i->_key.c_str());
+ if (j % 3 == 0)
+ con->DebugPrintf("\n");
+ j++;
+ }
+
+ con->DebugPrintf("\n");
+}
+
+void Vocabulary::copyParserListsFrom(Vocabulary *voc) {
+ voc->copyParserListsTo(_parserSuffixes, *_parserRules, _parserBranches, _parserWords);
+}
+
+void Vocabulary::copyParserListsTo(SuffixList &parserSuffixes, parse_rule_list_t &parserRules,
+ Common::Array<parse_tree_branch_t> &parserBranches, WordMap &parserWords) {
+ parserSuffixes = _parserSuffixes;
+ parserRules = *_parserRules;
+ parserBranches = _parserBranches;
+ parserWords = _parserWords;
+}
+
void _vocab_recursive_ptree_dump_treelike(parse_tree_node_t *nodes, int nr, int prevnr) {
if ((nr > VOCAB_TREE_NODES)/* || (nr < prevnr)*/) {
sciprintf("Error(%04x)", nr);
@@ -855,133 +634,4 @@ void vocab_synonymize_tokens(ResultWordList &words, const SynonymList &synonyms)
i->_group = sync->replacement;
}
-// Alternative kernel func names retriever. Required for KQ1/SCI (at least).
-static void _vocab_get_knames0alt(const Resource *r, Common::StringList &names) {
- uint idx = 0;
-
- while (idx < r->size) {
- Common::String tmp((const char *)r->data + idx);
- names.push_back(tmp);
- idx += tmp.size() + 1;
- }
-
- // The mystery kernel function- one in each SCI0 package
- names.push_back(SCRIPT_UNKNOWN_FUNCTION_STRING);
-}
-
-static void vocab_get_knames0(ResourceManager *resmgr, Common::StringList &names) {
- int count, i, index = 2, empty_to_add = 1;
- Resource *r = resmgr->findResource(kResourceTypeVocab, VOCAB_RESOURCE_KNAMES, 0);
-
- if (!r) { // No kernel name table found? Fall back to default table
- names.resize(SCI0_KNAMES_DEFAULT_ENTRIES_NR);
- for (i = 0; i < SCI0_KNAMES_DEFAULT_ENTRIES_NR; i++)
- names[i] = sci0_default_knames[i];
- return;
- }
-
- count = READ_LE_UINT16(r->data);
-
- if (count > 1023) {
- _vocab_get_knames0alt(r, names);
- return;
- }
-
- if (count < SCI0_KNAMES_WELL_DEFINED) {
- empty_to_add = SCI0_KNAMES_WELL_DEFINED - count;
- sciprintf("Less than %d kernel functions; adding %d\n", SCI0_KNAMES_WELL_DEFINED, empty_to_add);
- }
-
- names.resize(count + 1 + empty_to_add);
-
- for (i = 0; i < count; i++) {
- int offset = READ_LE_UINT16(r->data + index);
- int len = READ_LE_UINT16(r->data + offset);
- //fprintf(stderr,"Getting name %d of %d...\n", i, count);
- index += 2;
- names[i] = Common::String((const char *)r->data + offset + 2, len);
- }
-
- for (i = 0; i < empty_to_add; i++) {
- names[count + i] = SCRIPT_UNKNOWN_FUNCTION_STRING;
- }
-}
-
-static void vocab_get_knames1(ResourceManager *resmgr, Common::StringList &names) {
- // vocab.999/999.voc is notoriously unreliable in SCI1 games, and should not be used
- // We hardcode the default SCI1 kernel names here (i.e. the ones inside the "special"
- // 999.voc file from FreeSCI). All SCI1 games seem to be working with this change, but
- // if any SCI1 game has different kernel vocabulary names, it might not work. It seems
- // that all SCI1 games use the same kernel vocabulary names though, so this seems to be
- // a safe change. If there's any SCI1 game with different kernel vocabulary names, we can
- // add special flags to it to our detector
-
- names.resize(SCI1_KNAMES_DEFAULT_ENTRIES_NR);
- for (int i = 0; i < SCI1_KNAMES_DEFAULT_ENTRIES_NR; i++)
- names[i] = sci1_default_knames[i];
-}
-
-#ifdef ENABLE_SCI32
-static void vocab_get_knames11(ResourceManager *resmgr, Common::StringList &names) {
-/*
- 999.voc format for SCI1.1 games:
- [b] # of kernel functions
- [w] unknown
- [offset to function name info]
- ...
- {[w name-len][function name]}
- ...
-*/
- //unsigned int size = 64, pos = 3;
- int len;
- Resource *r = resmgr->findResource(kResourceTypeVocab, VOCAB_RESOURCE_KNAMES, 0);
- if(r == NULL) // failed to open vocab.999 (happens with SCI1 demos)
- return; // FIXME: should return a default table for this engine
- const byte nCnt = *r->data;
-
- names.resize(nCnt);
- for (int i = 0; i < nCnt; i++) {
- int off = READ_LE_UINT16(r->data + 2 * i + 2);
- len = READ_LE_UINT16(r->data + off);
- names[i] = Common::String((char *)r->data + off + 2, len);
- }
-}
-#endif
-
-bool Vocabulary::getKernelNames() {
- _kernelNames.clear();
-
- switch (_resmgr->_sciVersion) {
- case SCI_VERSION_0:
- case SCI_VERSION_01:
- vocab_get_knames0(_resmgr, _kernelNames);
- break;
- case SCI_VERSION_01_VGA:
- case SCI_VERSION_01_VGA_ODD:
- // HACK: KQ5 needs the SCI1 default vocabulary names to work correctly.
- // Having more vocabulary names (like in SCI1) doesn't seem to have any
- // ill effects, other than resulting in unmapped functions towards the
- // end, which are never used by the game interpreter anyway
- // return vocab_get_knames0(resmgr, count);
- case SCI_VERSION_1_EARLY:
- case SCI_VERSION_1_LATE:
- vocab_get_knames1(_resmgr, _kernelNames);
- break;
- case SCI_VERSION_1_1:
- vocab_get_knames1(_resmgr, _kernelNames);
- // KQ6CD calls unimplemented function 0x26
- _kernelNames[0x26] = "Dummy";
- break;
-#ifdef ENABLE_SCI32
- case SCI_VERSION_32:
- vocab_get_knames11(_resmgr, _kernelNames);
-#endif
- break;
- default:
- break;
- }
-
- return true;
-}
-
} // End of namespace Sci
diff --git a/engines/sci/vocabulary.h b/engines/sci/vocabulary.h
index cb4bb181d4..153317185f 100644
--- a/engines/sci/vocabulary.h
+++ b/engines/sci/vocabulary.h
@@ -178,12 +178,106 @@ struct parse_tree_node_t {
} content;
};
+enum VocabularyVersions {
+ kVocabularySCI0 = 0,
+ kVocabularySCI1 = 1
+};
+
class Vocabulary {
public:
- Vocabulary(EngineState *s);
+ Vocabulary(ResourceManager *resmgr, bool isOldSci0);
~Vocabulary();
/**
+ * Gets any word from the specified group. For debugging only.
+ * @param group Group number
+ */
+ const char *getAnyWordFromGroup(int group);
+
+
+ /* Looks up a single word in the words and suffixes list
+ ** Parameters: (char *) word: Pointer to the word to look up
+ ** (int) word_len: Length of the word to look up
+ ** Returns : (const ResultWordList &) A list containing 1 or 0 words
+ */
+ ResultWord lookupWord(const char *word, int word_len);
+
+
+ /* Tokenizes a string and compiles it into word_ts.
+ ** Parameters: (char *) sentence: The sentence to examine
+ ** (char **) error: Points to a malloc'd copy of the offending text or to NULL on error
+ ** (ResultWordList) retval: A list of word_ts containing the result, or NULL.
+ ** Returns : true on success, false on failure
+ ** On error, NULL is returned. If *error is NULL, the sentence did not contain any useful words;
+ ** if not, *error points to a malloc'd copy of the offending word.
+ ** The returned list may contain anywords.
+ */
+ bool tokenizeString(ResultWordList &retval, const char *sentence, char **error);
+
+ /* Builds a parse tree from a list of words, using a set of Greibach Normal Form rules
+ ** Parameters: (parse_tree_node_t *) nodes: A node list to store the tree in (must have
+ ** at least VOCAB_TREE_NODES entries)
+ ** (const ResultWordList &) words: The words to build the tree from
+ ** (parse_tree_branch_t *) branche0: The zeroeth original branch of the
+ ** original CNF parser grammar
+ ** bool verbose: Set to true for debugging
+ ** Returns : 0 on success, 1 if the tree couldn't be built in VOCAB_TREE_NODES nodes
+ ** or if the sentence structure in 'words' is not part of the language
+ ** described by the grammar passed in 'rules'.
+ */
+ int parseGNF(parse_tree_node_t *nodes, const ResultWordList &words, bool verbose = false);
+
+ /* Constructs the Greibach Normal Form of the grammar supplied in 'branches'
+ ** bool verbose: Set to true for debugging.
+ ** If true, the list is freed before the function ends
+ ** Returns : (parse_rule_list_t *): Pointer to a list of singly linked
+ ** GNF rules describing the same language
+ ** that was described by 'branches'
+ ** The original SCI rules are in almost-CNF (Chomsky Normal Form). Note that
+ ** branch[0] is used only for a few magical incantations, as it is treated
+ ** specially by the SCI parser.
+ */
+ parse_rule_list_t *buildGNF(bool verbose = false);
+
+ /* Decyphers a said block and dumps its content via sciprintf.
+ ** Parameters: (EngineState *) s: The state to use
+ ** (byte *) pos: Pointer to the data to dump
+ ** For debugging only.
+ */
+ void decypherSaidBlock(byte *pos);
+
+ /**
+ * Prints the parser suffixes to the debug console
+ */
+ void printSuffixes();
+
+ /**
+ * Prints the parser words to the debug console
+ */
+ void printParserWords();
+
+ /**
+ * Copies the parser lists from another vocabulary
+ */
+ void copyParserListsFrom(Vocabulary *voc);
+
+ /**
+ * Gets the internal parser lists, for vocabulary copying
+ */
+ void copyParserListsTo(SuffixList &parserSuffixes, parse_rule_list_t &parserRules,
+ Common::Array<parse_tree_branch_t> &parserBranches, WordMap &parserWords);
+
+ uint getParserBranchesSize() { return _parserBranches.size(); }
+ parse_tree_branch_t getParseTreeBranch(int number) { return _parserBranches[number]; }
+
+ Common::StringList _selectorNames;
+ Common::Array<opcode> _opcodes;
+ Common::StringList _kernelNames;
+
+ selector_map_t _selectorMap; /**< Shortcut list for important selectors */
+
+private:
+ /**
* Loads the vocabulary selector names.
* Returns true upon success, false otherwise.
*/
@@ -231,78 +325,22 @@ public:
*/
bool getBranches();
- /**
- * Gets any word from the specified group. For debugging only.
- * @param group Group number
- */
- const char *getAnyWordFromGroup(int group);
-
-
- /* Looks up a single word in the words and suffixes list
- ** Parameters: (char *) word: Pointer to the word to look up
- ** (int) word_len: Length of the word to look up
- ** Returns : (const ResultWordList &) A list containing 1 or 0 words
+ /* Frees a parser rule list as returned by vocab_build_gnf()
+ ** Parameters: (parse_rule_list_t *) rule_list: The rule list to free
*/
- ResultWord lookupWord(const char *word, int word_len);
+ void freeRuleList(parse_rule_list_t *rule_list);
+ ResourceManager *_resmgr;
+ bool _isOldSci0;
+ VocabularyVersions _vocabVersion;
- /* Tokenizes a string and compiles it into word_ts.
- ** Parameters: (char *) sentence: The sentence to examine
- ** (char **) error: Points to a malloc'd copy of the offending text or to NULL on error
- ** (ResultWordList) retval: A list of word_ts containing the result, or NULL.
- ** Returns : true on success, false on failure
- ** On error, NULL is returned. If *error is NULL, the sentence did not contain any useful words;
- ** if not, *error points to a malloc'd copy of the offending word.
- ** The returned list may contain anywords.
- */
- bool tokenizeString(ResultWordList &retval, const char *sentence, char **error);
-
- Common::StringList _selectorNames;
- Common::Array<opcode> _opcodes;
- Common::StringList _kernelNames;
- WordMap _parserWords;
+ // Parser-related lists
SuffixList _parserSuffixes;
+ parse_rule_list_t *_parserRules; /**< GNF rules used in the parser algorithm */
Common::Array<parse_tree_branch_t> _parserBranches;
- selector_map_t _selectorMap; /**< Shortcut list for important selectors */
-
-private:
- ResourceManager *_resmgr;
- bool _isOldSci0;
- int _vocabVersion;
+ WordMap _parserWords;
};
-/* Constructs the Greibach Normal Form of the grammar supplied in 'branches'
-** Parameters: (parse_tree_branch_t *) branches: The parser's branches
-** Returns : (parse_rule_list_t *): Pointer to a list of singly linked
-** GNF rules describing the same language
-** that was described by 'branches'
-** The original SCI rules are in almost-CNF (Chomsky Normal Form). Note that
-** branch[0] is used only for a few magical incantations, as it is treated
-** specially by the SCI parser.
-*/
-parse_rule_list_t *vocab_build_gnf(const Common::Array<parse_tree_branch_t> &branches, int verbose);
-
-
-/* Frees a parser rule list as returned by vocab_build_gnf()
-** Parameters: (parse_rule_list_t *) rule_list: The rule list to free
-*/
-void vocab_free_rule_list(parse_rule_list_t *rule_list);
-
-
-/* Builds a parse tree from a list of words
-** Parameters: (parse_tree_node_t *) nodes: A node list to store the tree in (must have
-** at least VOCAB_TREE_NODES entries)
-** (const ResultWordList &) words: The words to build the tree from
-** (parse_tree_branch_t *) branche0: The zeroeth original branch of the
-** original CNF parser grammar
-** (parse_rule_list *) rules: The GNF ruleset to parse with
-** Returns : 0 on success, 1 if the tree couldn't be built in VOCAB_TREE_NODES nodes
-** or if the sentence structure in 'words' is not part of the language
-** described by the grammar passed in 'rules'.
-*/
-int vocab_build_parse_tree(parse_tree_node_t *nodes, const ResultWordList &words,
- const parse_tree_branch_t &branch0, parse_rule_list_t *rules);
-
/* Prints a parse tree
** Parameters: (const char *) tree_name: Name of the tree to dump (free-form)
** (parse_tree_node_t *) nodes: The nodes containing the parse tree
@@ -320,23 +358,12 @@ void vocab_dump_parse_tree(const char *tree_name, parse_tree_node_t *nodes);
int said(EngineState *s, byte *spec, int verbose);
-/* Decyphers a said block and dumps its content via sciprintf.
-** Parameters: (EngineState *) s: The state to use
-** (byte *) pos: Pointer to the data to dump
-** For debugging only.
-*/
-void vocab_decypher_said_block(EngineState *s, byte *pos);
-
-
/* Synonymizes a token list
** Parameters: (ResultWordList &) words: The word list to synonymize
** (const SynonymList &) synonyms: Synonym list
*/
void vocab_synonymize_tokens(ResultWordList &words, const SynonymList &synonyms);
-int vocab_gnf_parse(parse_tree_node_t *nodes, const ResultWordList &words,
- const parse_tree_branch_t &branch0, parse_rule_list_t *tlist, int verbose);
-
int getAllocatedRulesCount();
} // End of namespace Sci