/*========================================================================= Program: bbtk Module: $RCSfile: bbtkInterpreter.cxx,v $ Language: C++ Date: $Date: 2010/09/14 07:18:46 $ Version: $Revision: 1.88 $ =========================================================================*/ /* --------------------------------------------------------------------- * Copyright (c) CREATIS-LRMN (Centre de Recherche en Imagerie Medicale) * Authors : Eduardo Davila, Laurent Guigues, Jean-Pierre Roux * * This software is governed by the CeCILL-B license under French law and * abiding by the rules of distribution of free software. You can use, * modify and/ or redistribute the software under the terms of the CeCILL-B * license as circulated by CEA, CNRS and INRIA at the following URL * http://www.cecill.info/licences/Licence_CeCILL-B_V1-en.html * or in the file LICENSE.txt. * * As a counterpart to the access to the source code and rights to copy, * modify and redistribute granted by the license, users are provided only * with a limited warranty and the software's author, the holder of the * economic rights, and the successive licensors have only limited * liability. * * The fact that you are presently reading this means that you have had * knowledge of the CeCILL-B license and that you accept its terms. * ------------------------------------------------------------------------ */ /** * \file * \brief class Interpreter : */ #include "bbtkInterpreterVirtual.h" //#include "bbtkTranscriptor.h" #include "bbtkConfigurationFile.h" #include "bbtkUtilities.h" //#include "bbtkAtomicBlackBox.h" //#include "bbtkWxBlackBox.h" #include #include #ifdef CMAKE_HAVE_TERMIOS_H #include #define BBTK_USE_TERMIOS_BASED_PROMPT #endif #include namespace bbtk { //======================================================================= InterpreterVirtual::Pointer InterpreterVirtual::New() { bbtkDebugMessage("kernel",9,"InterpreterVirtual::New()"<0 : Prints the output of the 'print' commands of the user.\n\tLevel>1 : Prints the command being interpreted",1); bbtk::MessageManager::RegisterMessageType("Interpreter","Messages of the interpreter",0); bbtkDebugMessageInc("Interpreter",9,"InterpreterVirtual::Interpreter()" < ~Interpreter()" <GetNoErrorMode()) //EED Borrame { //EED Borrame bbtkWarning("ERROR :"<GetNoErrorMode()) //EED Borrame { //EED Borrame std::string file("?"); //EED Borrame int line = 0; //EED Borrame if (mFileName.size()) { //EED Borrame file = mFileName.back(); //EED Borrame line = mLine.back(); //EED Borrame } //EED Borrame bbtkWarning("ERROR '"<(mFile.back()); if (fs!=0) in_script = true; file = mFileName.back(); line = mLine.back(); } if (e.GetErrorMessage()!="break") CloseAllFiles(); throw InterpreterException(e,in_script,file,line); } else { std::stringstream mess; mess << "* ERROR : "<GetNoErrorMode()) //EED Borrame { //EED Borrame std::string file("?"); //EED Borrame int line = 0; //EED Borrame if (mFileName.size()) { //EED Borrame file = mFileName.back(); //EED Borrame line = mLine.back(); //EED Borrame } //EED Borrame bbtkWarning("ERROR '"<(mFile.back()); if (fs!=0) in_script = true; file = mFileName.back(); line = mLine.back(); } CloseAllFiles(); throw InterpreterException(e.what(),in_script,file,line); } else { std::stringstream mess; mess << "* ERROR : "<GetNoErrorMode()) //EED Borrame { //EED Borrame std::string file("?"); //EED Borrame int line = 0; //EED Borrame if (mFileName.size()) { //EED Borrame file = mFileName.back(); //EED Borrame line = mLine.back(); //EED Borrame } //EED Borrame bbtkWarning("UNDEFINED ERROR " //EED Borrame <<"("<(mFile.back()); if (fs!=0) in_script = true; file = mFileName.back(); line = mLine.back(); } CloseAllFiles(); throw InterpreterException("Unknown exception caught", in_script,file,line); } else { std::stringstream mess; mess << "* UNDEFINED ERROR (not a bbtk nor a std exception)" << std::endl; if (mFileName.size()) { mess << "* FILE : \""< InterpreterVirtual::InterpretFile(\""< InterpreterVirtual::InterpretBuffer()"< InterpreterVirtual::InterpretCurrentStreams()"<0) { while (!mFile.back()->eof()) { mLine.back()++; char buf[500]; mFile.back()->getline(buf,500); std::string str(buf); //size 0 JCP 21-09-2009 int size=str.length(); if(size != 0){ if ( str[ size-1 ]==13 ) { str.erase(size-1,1); } try { DoInterpretLine(str); } CATCH_MACRO; } } CloseCurrentFile(); } bbtkDebugMessage("interpreter",4, "<== InterpreterVirtual::InterpretCurrentStreams()"< InterpreterVirtual::InterpretLine('"< InterpreterVirtual::DoInterpretLine(\"" < words; SplitLine(line,words); printf("EED %p InterpreterVirtual::DoInterpretLine word.size %d \n", this, (int)words.size() ); // Empty line if (words.size()<1) { bbtkDebugDecTab("interpreter",9); return; } // Single line comment : # or // if ( words[0][0]=='#' || (words[0][0]=='/' && words[0][1]=='/') ) { bbtkDebugDecTab("interpreter",9); bbtkMessage("interpreter",9,"Comment"<SetMessageLevel(words[1],level); } return; } else { bbtkMessage("echo",2,line<(mFile.back()); if (fs!=0) in_script = true; file = mFileName.back(); line = mLine.back(); } if (command.code==cBreak) { /* std::cout << "BreakException(" <Create(words[1],words[2]); "<Create(words[1],words[2]); break; case cDelete : commandDelete(words[1]); //EED Borrame mVirtualExecuter->Destroy(words[1]); break; case cConnect : Utilities::SplitAroundFirstDot(words[1],left,right); Utilities::SplitAroundFirstDot(words[2],left2,right2); commandConnection(left,right,left2,right2); //EED Borrame mVirtualExecuter->Connect(left,right,left2,right2); break; case cPackage : commandPackage(words[1]); //EED Borrame mVirtualExecuter->BeginPackage(words[1]); break; case cEndPackage : commandEndPackage(); //EED Borrame mVirtualExecuter->EndPackage(); break; case cDefine : if (mFileName.size()>0) { //??? commandDefine(????); filename = mFileName.back(); //mIncludeFileName.back(); //Utilities::get_file_name(mFileName.back()); } if (words.size()==2) { commandDefine(words[1],"",filename); //EED Borrame mVirtualExecuter->Define(words[1],"",filename); } else { commandDefine(words[1],words[2],filename); //EED Borrame mVirtualExecuter->Define(words[1],words[2],filename); } break; case cEndDefine : commandEndDefine(); //EED Borrame mVirtualExecuter->EndDefine(); break; case cKind : commandKind(words[1]); //EED Borrame mVirtualExecuter->Kind(words[1]); break; case cPrint : commandPrint(words[1]); //EED Borrame mVirtualExecuter->Print(words[1]); break; case cExec : commandExec(words[1]); //EED Borrame if (words[1]=="freeze") //EED Borrame { //EED Borrame mVirtualExecuter->SetNoExecMode(true); //EED Borrame mThrow = false; //EED Borrame } //EED Borrame else if (words[1]=="freeze_no_error") //EED Borrame { //EED Borrame mVirtualExecuter->SetNoExecMode(true); //EED Borrame mVirtualExecuter->SetNoErrorMode(true); //EED Borrame mThrow = false; //EED Borrame } //EED Borrame else if (words[1]=="unfreeze") //EED Borrame { //EED Borrame mVirtualExecuter->SetNoExecMode(false); //EED Borrame mVirtualExecuter->SetNoErrorMode(false); //EED Borrame } //EED Borrame else //EED Borrame { //EED Borrame mVirtualExecuter->Execute(words[1]); //EED Borrame } break; case cInput : Utilities::SplitAroundFirstDot(words[2],left,right); commandInput(words[1],left,right,words[3]); //EED Borrame mVirtualExecuter->DefineInput(words[1],left,right,words[3]); break; case cOutput : Utilities::SplitAroundFirstDot(words[2],left,right); commandOutput(words[1],left,right,words[3]); //EED Borrame mVirtualExecuter->DefineOutput(words[1],left,right,words[3]); break; case cSet : Utilities::SplitAroundFirstDot(words[1],left,right); commandSet(left,right,words[2]); //EED Borrame mVirtualExecuter->Set(left,right,words[2]); break; case cAuthor : commandAuthor(words[1]); //EED Borrame mVirtualExecuter->Author(words[1]); break; case cNewGUI : commandNewGUI(words[1],words[2]); break; case cCategory : commandCategory(words[1]); //EED Borrame mVirtualExecuter->Category(words[1]); break; case cIndex : if (words.size()==1) commandIndex("tmp_index.html"); else if (words.size()==2) commandIndex(words[1]); else if (words.size()==3) commandIndex(words[1],words[2]); break; case cDescription : commandDescription(words[1]); //EED Borrame mVirtualExecuter->Description(words[1]); break; case cHelp : commandHelp(words); break; case cGraph : commandGraph(words); break; case cConfig : commandConfig(); break; case cReset : commandReset(); break; case cClear : commandClear(); //EED Borrame mVirtualExecuter->Clear(); break; case cInclude : commandInclude( words[1] , (words.size()==3) ); //EED Borrame // if 'source' was given (words.size()==3) then tell to set the //EED Borrame // source file name of the current complex box with the full file name included //EED Borrame if (mCommandLine) //EED Borrame { //EED Borrame InterpretFile(words[1],(words.size()==3)); //EED Borrame } else{ //EED Borrame SwitchToFile(words[1],(words.size()==3) ); //EED Borrame } break; case cLoad: commandLoad( words[1] ); //EED Borrame GetExecuter()->LoadPackage(words[1]); break; case cUnload: commandUnload( words[1] ); //EED Borrame GetExecuter()->UnLoadPackage(words[1]); break; case cDebug : if (words.size()==2) commandDebug(words[1]); else commandDebug(""); break; /* obsolete case cWorkspace : if (words.size() == 2) { if (words[1]=="freeze") mVirtualExecuter->SetNoExecMode(true); else if (words[1]=="unfreeze") mVirtualExecuter->SetNoExecMode(false); } else { mVirtualExecuter->SetWorkspaceName(words[2]); } break; */ default: bbtkInternalError("should not reach here !!!"); } bbtkDebugMessage("interpreter",6,"<== InterpreterVirtual::DoInterpretLine(\"" <& tokens) { bbtkDebugMessage("interpreter",9,"==> InterpreterVirtual::SplitLine(\""< quote; Utilities::SplitString(str,delimiters,quote); delimiters = " \t"; std::vector::iterator i; for (i=quote.begin(); i!=quote.end(); ) { Utilities::SplitString(*i,delimiters,tokens); ++i; if (i!=quote.end()) { // bbtkDebugMessage("interpreter",0,"\""<<*i<<"\""<GetNoExecMode()) return; bbtkDebugMessageInc("interpreter",9,"InterpreterVirtual::Print(\""< trouver un nom unique : # commande // InterpretLine("new Print _P_") // InterpretLine("connect _C_.Out _P_.In") // int num = 1 std::vector chains; std::string delimiters("$"); // Skip delimiters at beginning. std::string::size_type lastPos = str.find_first_not_of(delimiters, 0); bool is_text = true; if (lastPos>0) is_text = false; // Find first delimiter. std::string::size_type pos = str.find_first_of(delimiters, lastPos); while (std::string::npos != pos || std::string::npos != lastPos) { if (is_text) { // Found a text token, add it to the vector. chains.push_back(str.substr(lastPos, pos - lastPos)); // std::string token = str.substr(lastPos, pos - lastPos) // InterpretLine("set _C_.In%num% %token%") } else { // is an output (between $$) : decode std::string tok,box,output; tok = str.substr(lastPos, pos - lastPos); Utilities::SplitAroundFirstDot(tok,box,output); chains.push_back( mVirtualExecuter->Get(box,output) ); // InterpretLine("connect %tok% _C_.In%num%") } // Skip delimiters. Note the "not_of" lastPos = str.find_first_not_of(delimiters, pos); // Find next delimiter pos = str.find_first_of(delimiters, lastPos); // is_text = !is_text; // num ++; } // InterpretLine("exec _P_") // if (IS_IN_WORKSPACE) InterpretLine("delete _C_; delete _P_"); std::vector::iterator i; for (i= chains.begin(); i!=chains.end(); ++i) { Utilities::SubsBackslashN(*i); std::cout << *i; } std::cout << std::endl; bbtkDebugDecTab("interpreter",9); } */ //======================================================================= /** * */ // ========================================================================= void InterpreterVirtual::SwitchToFile( const std::string& name , bool source ) { printf("EED InterpreterVirtual::SwitchToFile 1\n"); printf("EED InterpreterVirtual::SwitchToFile name=%s\n", name.c_str() ); // Note : in the following : // name : the user supplied name // - abreviated name e.g. scr scr.bbs // - relative full name e.g. ./scr.bbs ../../scr.bbs // - absolute full name e.g. /home/usrname/proj/dir/scr.bbs // same for Windows, with c:, d: ... // // use ./directory/subdir/scrname.bbs // bbtkDebugMessage("interpreter",4,"==> InterpreterVirtual::SwitchToFile( \"" < script_paths; std::string fullPathScriptName; // full path script name std::string pkgname; // e.g. .bbs std::vector Filenames; // The following is *NOT* a debug time message : // It's a user intended message. // Please don't remove it. bbtkMessage("interpreter",1, "look for : [" << name << "]" << std::endl); std::string upath; pkgname = Utilities::ExtractScriptName(name,upath); bbtkMessage("interpreter",3, "package name:[" << pkgname << "] path:[" << upath << "]" << std::endl); bool fullnameGiven = false; bool foundFile = false; // ==== "*" provided : load all scripts in given path // relative (e.g. std/boxes/*) or absolute if (pkgname == "*") { std::stringstream* stream = new std::stringstream; //if (upath.size()!=0) // avoid troubles for "*" printf("EED InterpreterVirtual::SwitchToFile 2\n"); // ==== no path provided : look in root bbs path if (upath.size()==0) { // bbtkMessage("interpreter",1, // LG : add all bbs path // script_paths.push_back( ConfigurationFile::GetInstance().Get_root_bbs_path() ); std::vector::const_iterator i; for (i=ConfigurationFile::GetInstance().Get_bbs_paths().begin(); i!=ConfigurationFile::GetInstance().Get_bbs_paths().end(); i++) { script_paths.push_back(*i); } } // ==== absolute path provided else if (upath[0]=='/' || upath[1] == ':' ) { if ( Utilities::IsDirectory( upath ) ) { script_paths.push_back(upath); } else { bbtkError("'"<::const_iterator i; for (i=ConfigurationFile::GetInstance().Get_bbs_paths().begin(); i!=ConfigurationFile::GetInstance().Get_bbs_paths().end(); i++) { std::string full_path(*i); // we *really* want '.' to be the current working directory if (full_path == ".") { char buf[2048]; // for getcwd char * currentDir = getcwd(buf, 2048); std::string cwd(currentDir); full_path = currentDir; } // if full_path full_path += ConfigurationFile::GetInstance().Get_file_separator(); full_path += upath; if ( Utilities::IsDirectory( full_path ) ) { script_paths.push_back(full_path); } } if (script_paths.empty()) { bbtkError("no '"<::iterator i; for (i=script_paths.begin();i!=script_paths.end();i++) { bbtkMessage("interpreter",1, "--> Looking in '" << *i << "'" << std::endl); Filenames.clear(); //int nbFiles = Utilities::Explore(*i, false, Filenames); for (std::vector::iterator j = Filenames.begin(); j!= Filenames.end(); ++j) { int lgr = (*j).size(); if (lgr < 5) continue; // ignore non .bbp file if ( (*j).substr(lgr-4, 4) != ".bbp") continue; (*stream) << "include \"" << *j << "\"\n"; bbtkMessage("interpreter",2," --> Found '" << *j << "'" << std::endl); nbBssFiles++; } // for (std::vector... } // for (i=script_... // === Result ... if (nbBssFiles==0) { bbtkMessage("interpreter",1, " --> No .bbp found"<< std::endl); } else { bbtkMessage("interpreter",1, " --> "<::iterator i; for (i=script_paths.begin();i!=script_paths.end();++i) { path = *i; // we *really* want '.' to be the current working directory if (path == ".") { char buf[2048]; // for getcwd char * currentDir = getcwd(buf, 2048); std::string cwd(currentDir); path = currentDir; } std::string tfullPathScriptName = Utilities::MakePkgnameFromPath(path, name, false); //Addition JCP tfullPathScriptName.size()>=4 if(tfullPathScriptName.size()>=4){ if (tfullPathScriptName.substr(tfullPathScriptName.size()-4, 3)==".bb") { fullPathScriptName = tfullPathScriptName; if ( ! Utilities::FileExists(fullPathScriptName) ) { // The following is *NOT* a debug time message : // It's a user intended message. // Please don't remove it. bbtkMessage("interpreter",2, " [" <SetCurrentFileName(fullPathScriptName); if (source) SetCurrentFileName(fullPathScriptName); } printf("EED InterpreterVirtual::SwitchToFile 4\n"); return; } //======================================================================= //======================================================================= void InterpreterVirtual::SetCurrentFileName(std::string fullPathScriptName) // virtual { printf("EED InterpreterVirtual::SetCurrentFileName 1\n"); } //======================================================================= //======================================================================= void InterpreterVirtual::SwitchToStream( std::stringstream* stream ) { printf("EED InterpreterVirtual::SwitchToStream 1\n"); bbtkDebugMessage("interpreter",4,"==> InterpreterVirtual::SwitchToStream()" <0 ) { buffer_name << mFileName.back() << "_" << mLine.back(); } mFileName.push_back(buffer_name.str()); mIncludeFileName.push_back(buffer_name.str()); mLine.push_back(0); } //======================================================================= //======================================================================= void InterpreterVirtual::LoadScript( std::string fullPathScriptName, std::string includeScriptName) { bbtkDebugMessage("interpreter",4,"==> InterpreterVirtual::LoadScript(" <open(fullPathScriptName.c_str()); if (!s->good()) { bbtkError("Could not open file ["<[" << fullPathScriptName << "] found" << std::endl); mFile.push_back(s); mFileName.push_back(fullPathScriptName); mFileNameHistory.push_back(fullPathScriptName); mIncludeFileName.push_back(includeScriptName); mLine.push_back(0); return; } //======================================================================= //======================================================================= void InterpreterVirtual::CloseCurrentFile() { bbtkDebugMessage("interpreter",9,"==> InterpreterVirtual::CloseCurrentFile()" < no file left open"<(mFile.back()); if (file!=0) file->close(); delete mFile.back(); mFile.pop_back(); mFileName.pop_back(); mIncludeFileName.pop_back(); mLine.pop_back(); bbtkDebugMessage("interpreter",9," Remains " < InterpreterVirtual::CloseAllFiles()" <& words, CommandInfoType& info ) { printf("EED InterpreterVirtual::InterpretCommand 1 \n"); bbtkDebugMessage("interpreter",9,"==> InterpreterVirtual::InterpretCommand(...)"<second.argmin ) || ( ((int)words.size())-1 > c->second.argmax ) ) { //EED HelpCommand(words[0]); commandHelp(words[0]); printf("EED InterpreterVirtual::InterpretCommand 3 \n"); bbtkError(words[0]<<" : wrong number of arguments"); } //std::cout<<"InterpreterVirtual::InterpretCommand( const std::vector& words,"<second; printf("EED InterpreterVirtual::InterpretCommand 4 \n" ); bbtkDebugMessage("interpreter",9,"<== InterpreterVirtual::InterpretCommand(...)"<& words) { } //======================================================================= void InterpreterVirtual::commandHelp(const std::string words) { } //======================================================================= //=================================================================== /// Displays the Configuration void InterpreterVirtual::commandConfig() const { } //=================================================================== //======================================================================= /// Fills the vector commands with the commands which /// have the first n chars of buf for prefix /// TODO : skip initial spaces in buf and also return the position of first /// non blank char in buf void InterpreterVirtual::FindCommandsWithPrefix( char* buf, int n, std::vector& commands ) { CommandDictType::const_iterator i; for (i=mCommandDict.begin(); i!=mCommandDict.end(); ++i) { if ((i->first).find(buf,0,n) == 0) commands.push_back(i->first); } } //======================================================================= //======================================================================= #ifdef BBTK_USE_TERMIOS_BASED_PROMPT inline void PrintChar(char c) { write(STDOUT_FILENO,&c,1); } inline void BackSpace() { write(STDOUT_FILENO,"\b \b",3); } // LG : KEYBOARD CODES AS SCANNED ON MY TTY : UNIVERSAL ? // IF NOT THE USER SHOULD BE ABLE TO CONFIGURE IT // E.G. STORE THIS IN bbtk_config.xml #define BBTK_UP_ARROW_KBCODE 0x00415B1B #define BBTK_DOWN_ARROW_KBCODE 0x00425B1B #define BBTK_RIGHT_ARROW_KBCODE 0x00435B1B #define BBTK_LEFT_ARROW_KBCODE 0x00445B1B #define BBTK_BACKSPACE_KBCODE 0x00000008 #define BBTK_DEL_KBCODE 0x0000007F #define BBTK_SPACE_KBCODE 0x00000020 //======================================================================= void InterpreterVirtual::GetLineFromPrompt(std::string& s) { int c; unsigned int ind=0; unsigned int MAX_LINE_SIZE = 160; unsigned int MAX_HISTORY_SIZE = 100; char* newline = new char[MAX_LINE_SIZE]; memset(newline,0,MAX_LINE_SIZE); char* histline = new char[MAX_LINE_SIZE]; memset(histline,0,MAX_LINE_SIZE); char* line = newline; unsigned int hist = mHistory.size(); write(1,"> ",2); while(1) { c=0; read ( STDIN_FILENO, &c, 4) ; bbtkDebugMessage("debug",9,"[0x"<= BBTK_SPACE_KBCODE ) && ( c < BBTK_DEL_KBCODE )) { PrintChar(c); line[ind++]=c; } // CR else if (c=='\n') { // delete the unused line if (line==newline) delete histline; else delete newline; // empty lines are not stored in from history if (strlen(line)) { // if history too long : delete oldest command if (mHistory.size()>MAX_HISTORY_SIZE) { delete mHistory.front(); mHistory.pop_front(); } mHistory.push_back(line); } break; } // Backspace else if ( (ind>0) && ((c == BBTK_BACKSPACE_KBCODE) || (c == BBTK_DEL_KBCODE)) ) { line[ind--]=' '; BackSpace(); } // Tab else if (c=='\t') { // TODO : Command completion std::vector commands; FindCommandsWithPrefix( line,ind,commands); if (commands.size()==1) { std::string com = *commands.begin(); for (; ind1) { std::vector::iterator i; write(1,"\n",1); for (i=commands.begin();i!=commands.end();++i) { write(STDOUT_FILENO,(*i).c_str(),strlen((*i).c_str())); PrintChar(' '); } write(STDOUT_FILENO,"\n> ",3); //for (int j=0;j0 && c==BBTK_LEFT_ARROW_KBCODE) { PrintChar('\b'); ind--; } } write(STDOUT_FILENO,"\n\r",2); s = line; } #else //======================================================================= void InterpreterVirtual::GetLineFromPrompt(std::string& s) { s.clear(); putchar('>'); putchar(' '); do { char c = getchar(); if (c=='\n') { putchar('\n'); break; } if (c=='\t') { // putchar('T'); continue; } // putchar(c); s += c; } while (true); } //======================================================================= #endif //======================================================================= void InterpreterVirtual::CommandLineInterpreter() { bbtkDebugMessageInc("interpreter",9, "InterpreterVirtual::CommandLineInterpreter()"<& words) { } //======================================================================= //======================================================================= void InterpreterVirtual::commandIndex(const std::string& filename, const std::string& type) { } //======================================================================= //======================================================================= void InterpreterVirtual::commandNewGUI(const std::string& boxname,const std::string& instanceName) { } //======================================================================= //========================================================================== void InterpreterVirtual::commandDebug(const std::string& name) { } //========================================================================== /* //========================================================================== // Adds a callback when 'break' command issued void InterpreterVirtual::AddBreakObserver( BreakCallbackType c ) { mBreakSignal.connect(c); } //========================================================================== */ //========================================================================== std::string InterpreterVirtual::GetObjectName() const { return std::string("InterpreterVirtual"); } //========================================================================== //========================================================================== std::string InterpreterVirtual::GetObjectInfo() const { std::stringstream i; return i.str(); } //========================================================================== //========================================================================== size_t InterpreterVirtual::GetObjectSize() const { size_t s = Superclass::GetObjectSize(); s += InterpreterVirtual::GetObjectInternalSize(); return s; } //========================================================================== //========================================================================== size_t InterpreterVirtual::GetObjectInternalSize() const { size_t s = sizeof(InterpreterVirtual); return s; } //========================================================================== //========================================================================== size_t InterpreterVirtual::GetObjectRecursiveSize() const { size_t s = Superclass::GetObjectRecursiveSize(); s += InterpreterVirtual::GetObjectInternalSize(); return s; } //========================================================================== }//namespace