#include "command.h" #include <regex.h> #include <fstream.h> #pragma implementation static StringReHash command_constants; CommandNode::CommandNode(Val_List* key, String* indata, CommandNode* nextnode){ key_list = key; data = indata; next = nextnode; } CommandNode::~CommandNode(){ delete key_list; delete data; delete next; } CommandList::CommandList(){ clist = NULL; } CommandList::~CommandList(){ delete clist; } String* CommandList::add (Val_List* key, String* indata){ if (key && key->ok_command()) {clist = new CommandNode (key, new String (*indata), clist); return indata;} else {return NULL;} } int CommandList::remove (String* pattern){ CommandNode** clist_ptr, *templist; Val_List* vlist; for (clist_ptr = &clist ; *clist_ptr ; clist_ptr = &((*clist_ptr)->next)) if (vlist = (*clist_ptr)->key_list->command_match (*pattern)) {delete vlist; templist = *clist_ptr; *clist_ptr = templist->next; templist->next = NULL; delete templist; return 1;} return 0; } Value* list_lookup (Val_List* parse_list, String* pattern, String** error_string = NULL){ Val_List* retval=NULL; if ((!parse_list) || (!parse_list->ok_command())) {if (error_string && !(*error_string)) *error_string = new String ("Invalid sentence passed to match-one"); return new Value (E_INVALID_REGEXP, ERR);} retval = parse_list->command_match (*pattern); return new Value (retval); } void CommandList::purge (){ delete clist; clist = NULL; } String* CommandList::lookup (String* pattern){ CommandNode* templist; Val_List* vlist; for (templist = clist ; templist ; templist = templist->next) if (vlist = templist->key_list->command_match (*pattern)) {delete vlist; return templist->data;} return NULL; } Val_List* CommandList::lookup_all (String* pattern){ Val_List* retval = NULL; Val_List* vlist; CommandNode* traverser; for (traverser = clist ; traverser ; traverser = traverser->next) if (vlist = traverser->key_list->command_match (*pattern)) {retval = new Val_List (new Value (new Val_List (new Value (new String (*traverser->data), SYM), new Val_List (new Value (vlist)))), retval);} return retval; } Value* CommandList::list_cmds(){ Val_List* biglist = NULL, *outlist; CommandNode* traverser; for (traverser = clist ; traverser ; traverser = traverser->next) {outlist = new Val_List (new Value (new String (*traverser->data), SYM)); outlist = new Val_List ((new Value (traverser->key_list->copy())), outlist); biglist = new Val_List ((new Value (outlist)), biglist);} return new Value (biglist); } char* CommandList::pack_cmds (char* buf){ CommandNode* traverser; long len; for (traverser = clist ; traverser ; traverser = traverser->next) {strcpy (buf , (char*)traverser->data->chars()); buf += traverser->data->length() + 1; len = traverser->key_list->length(); PACK_INT(buf, len); buf += sizeof (long); buf = traverser->key_list->pack_list (buf);} *buf = '\0'; return ++buf; } char* CommandList::unpack (char* buf){ String* tempstring; Val_List* templist; long len; delete clist; for (clist = NULL ; *buf ;) {tempstring = new String (buf); buf += tempstring->length() + 1; UNPACK_INT (buf, len); buf += sizeof (long); for (templist = NULL ; len ; len--) templist = new Val_List (unpack_value (&buf), templist); clist = new CommandNode (templist , tempstring , clist);} return buf+1; } void CommandList::dump_to_stdout(){ CommandNode* traverser; Value* tempval; for (traverser = clist ; traverser ; traverser = traverser->next) {tempval = new Value (traverser->key_list->copy()); tempval->tostr(); cout << *tempval->str; tempval->release(); cout << "\n" << *(traverser->data) << "\n";} } /**************************************************************** ******** StringReHash implementation **************************** *****************************************************************/ #define SSH_HASH(s) (((s)[0] + (s)[1]) % SSH_WIDTH) StringPtrList::StringPtrList (String* inkey, void* indata, StringPtrList* next_node = NULL){ key = inkey; data = indata; next = next_node; } StringPtrList::~StringPtrList(){ delete key; delete data; delete next; } StringPtrHash::StringPtrHash(){ int i; for (i=0 ; i<SSH_WIDTH ; i++) slists[i] = NULL; } StringPtrHash::~StringPtrHash(){ int i; for (i=0 ; i<SSH_WIDTH ; i++) delete slists[i]; } void StringPtrHash::add (String* key, void* data){ int index; char* stringkey; stringkey = (char*)key->chars(); index = SSH_HASH(stringkey); slists[index] = new StringPtrList (key, data, slists[index]); } void* StringPtrHash::lookup (String* key){ int index; char* stringkey; StringPtrList* sptr; stringkey = (char*)key->chars(); index = SSH_HASH(stringkey); for (sptr = slists[index] ; sptr ; sptr=sptr->next) if (!fcompare(*key, *(sptr->key))) return sptr->data; return NULL; } void StringReHash::add (String* key, Regex* data){ StringPtrHash::add (key, ((void*) data)); } Regex* StringReHash::lookup (String* key){ return (Regex*) StringPtrHash::lookup (key); } /**************************************************************** ******** code for the command_constants ************************* *****************************************************************/ void sub_special (String& instr){ instr.gsub ("\\\\" , "\1"); instr.gsub ("\\n" , "\n"); instr.gsub ("\\t" , "\t"); instr.gsub ("\\\"" , "\""); instr.gsub ("\\" , ""); instr.gsub ("\1" , "\\"); }; void initialize_command_constants(){ int i; ifstream command_file ("COMMAND_CONSTANTS"); String sym, regex; if (command_file.fail()) {cerr << "COMMAND_CONSTANTS file not found\nUnable to initialize\n"; exit(1);} for (i=0 ; readline(command_file, sym, ' ') ; i++) {readline(command_file, regex); sub_special (regex); command_constants.add (new String (sym), new Regex ((char*)regex.chars()));} cout << i << " command constants found in COMMAND_CONSTANTS\n"; } int is_command_constant (String* key){ return (int)(command_constants.lookup (key)); } String* match_command_constant (String* key, String& pattern){ Regex* re; if (re = command_constants.lookup (key)) if (pattern.contains(*re)) return new String (pattern.through (*re)); return NULL; } Regex* get_command_constant(String* key){ return command_constants.lookup (key); }