diff --git a/src/core/chuck.cpp b/src/core/chuck.cpp index 3bfc0d531..631d8bc1f 100644 --- a/src/core/chuck.cpp +++ b/src/core/chuck.cpp @@ -713,7 +713,7 @@ t_CKBOOL ChucK::initChugins() EM_pushlog(); // print host version - EM_log( CK_LOG_SEVERE, TC::green("host version: %d.%d", true).c_str(), CK_DLL_VERSION_MAJOR, CK_DLL_VERSION_MINOR ); + EM_log( CK_LOG_SEVERE, TC::green("host API version: %d.%d", true).c_str(), CK_DLL_VERSION_MAJOR, CK_DLL_VERSION_MINOR ); EM_poplog(); //--------------------------------------------------------------------- @@ -825,7 +825,7 @@ void ChucK::probeChugins() // print whether chugins enabled EM_log( CK_LOG_SYSTEM, "chugin system: %s", getParamInt( CHUCK_PARAM_CHUGIN_ENABLE ) ? "ON" : "OFF" ); // print host version - EM_log( CK_LOG_SYSTEM, TC::green("host version: %d.%d", true).c_str(), CK_DLL_VERSION_MAJOR, CK_DLL_VERSION_MINOR ); + EM_log( CK_LOG_SYSTEM, TC::green("host API version: %d.%d", true).c_str(), CK_DLL_VERSION_MAJOR, CK_DLL_VERSION_MINOR ); // push EM_pushlog(); // print host version diff --git a/src/core/chuck_compile.cpp b/src/core/chuck_compile.cpp index b54da266d..c999d933c 100644 --- a/src/core/chuck_compile.cpp +++ b/src/core/chuck_compile.cpp @@ -976,9 +976,12 @@ t_CKBOOL load_external_module_at_path( Chuck_Compiler * compiler, const char * name, const char * dl_path ) { + // get env Chuck_Env * env = compiler->env(); - // EM_log(CK_LOG_SEVERE, "loading chugin '%s'", name); + // log with no newline; print status next + // NOTE this is more informative if the chugin crashes, we can see the name + EM_log_opts( CK_LOG_SEVERE, EM_LOG_NO_NEWLINE, "[%s] %s ", TC::magenta("chugin",true).c_str(), name ); Chuck_DLL * dll = new Chuck_DLL( compiler->carrier(), name ); t_CKBOOL query_failed = FALSE; @@ -992,7 +995,7 @@ t_CKBOOL load_external_module_at_path( Chuck_Compiler * compiler, if( !dll->compatible() ) { // print - EM_log( CK_LOG_SEVERE, "[%s] loading chugin %s (%d.%d)", TC::red("FAILED",true).c_str(), name, dll->versionMajor(), dll->versionMinor() ); + EM_log_opts( CK_LOG_SEVERE, EM_LOG_NO_PREFIX, "[%s] (API version: %d.%d)", TC::red("FAILED",true).c_str(), dll->versionMajor(), dll->versionMinor() ); // push EM_pushlog(); EM_log( CK_LOG_SEVERE, "reason: %s", TC::orange(dll->last_error(),true).c_str() ); @@ -1007,7 +1010,7 @@ t_CKBOOL load_external_module_at_path( Chuck_Compiler * compiler, if( query_failed || !type_engine_add_dll2( env, dll, "global" ) ) { // print - EM_log( CK_LOG_SEVERE, "[%s] loading chugin %s (%d.%d)", TC::red("FAILED",true).c_str(), name, dll->versionMajor(), dll->versionMinor() ); + EM_log_opts( CK_LOG_SEVERE, EM_LOG_NO_PREFIX, "[%s] (API version: %d.%d)", TC::red("FAILED",true).c_str(), dll->versionMajor(), dll->versionMinor() ); EM_pushlog(); // if add_dll2 failed, an error should have already been output if( query_failed ) @@ -1024,7 +1027,7 @@ t_CKBOOL load_external_module_at_path( Chuck_Compiler * compiler, else { // print - EM_log( CK_LOG_SEVERE, "[%s] chugin '%s' load...", TC::red("FAILED",true).c_str(), name ); + EM_log_opts( CK_LOG_SEVERE, EM_LOG_NO_PREFIX, "[%s]", TC::red("FAILED",true).c_str() ); // more info EM_pushlog(); EM_log( CK_LOG_SEVERE, "reason: %s", TC::orange(dll->last_error(),true).c_str() ); @@ -1034,7 +1037,7 @@ t_CKBOOL load_external_module_at_path( Chuck_Compiler * compiler, } // print - EM_log( CK_LOG_SEVERE, "[%s] chugin %s (%d.%d)", TC::green("OK",true).c_str(), name, dll->versionMajor(), dll->versionMinor() ); + EM_log_opts( CK_LOG_SEVERE, EM_LOG_NO_PREFIX, "[%s] (API version: %d.%d)", TC::green("OK",true).c_str(), dll->versionMajor(), dll->versionMinor() ); // add to compiler compiler->m_dlls.push_back(dll); // commit operator overloads | 1.5.1.5 @@ -1192,6 +1195,10 @@ t_CKBOOL probe_external_module_at_path( const char * name, const char * dl_path // create dynamic module Chuck_DLL * dll = new Chuck_DLL( NULL, name ); + // log with no newline; print status next + // NOTE this is more informative if the chugin crashes, we can see the name + EM_log_opts( CK_LOG_SYSTEM, EM_LOG_NO_NEWLINE, "[%s] %s ", TC::magenta("chugin",true).c_str(), name ); + // load the dll, lazy mode if( dll->load(dl_path, CK_QUERY_FUNC, TRUE) ) { @@ -1201,12 +1208,14 @@ t_CKBOOL probe_external_module_at_path( const char * name, const char * dl_path if( dll->compatible() ) { // print - EM_log( CK_LOG_SYSTEM, "[%s] chugin %s (%d.%d)", TC::green("OK",true).c_str(), name, dll->versionMajor(), dll->versionMinor() ); + EM_log_opts( CK_LOG_SYSTEM, EM_LOG_NO_PREFIX, "[%s] (API version: %d.%d)", TC::green("OK",true).c_str(), + dll->versionMajor(), dll->versionMinor() ); } else { // print - EM_log( CK_LOG_SYSTEM, "[%s] chugin %s (%d.%d)", TC::red("FAILED",true).c_str(), name, dll->versionMajor(), dll->versionMinor() ); + EM_log_opts( CK_LOG_SYSTEM, EM_LOG_NO_PREFIX, "[%s] (API version: %d.%d)", TC::red("FAILED",true).c_str(), + dll->versionMajor(), dll->versionMinor() ); // push EM_pushlog(); EM_log( CK_LOG_SYSTEM, "reason: %s", TC::orange(dll->last_error(),true).c_str() ); @@ -1217,7 +1226,7 @@ t_CKBOOL probe_external_module_at_path( const char * name, const char * dl_path else { // print - EM_log( CK_LOG_SYSTEM, "[%s] chugin '%s' load...", TC::red("FAILED",true).c_str(), name ); + EM_log_opts( CK_LOG_SYSTEM, EM_LOG_NO_PREFIX, "[%s]...", TC::red("FAILED",true).c_str() ); // more info EM_pushlog(); EM_log( CK_LOG_SYSTEM, "reason: %s", TC::orange(dll->last_error(),true).c_str() ); diff --git a/src/core/chuck_dl.cpp b/src/core/chuck_dl.cpp index 06998d6bc..f960ddaf3 100644 --- a/src/core/chuck_dl.cpp +++ b/src/core/chuck_dl.cpp @@ -861,7 +861,7 @@ t_CKBOOL Chuck_DLL::load( const char * filename, const char * func, t_CKBOOL laz t_CKBOOL Chuck_DLL::load( f_ck_query query_func, t_CKBOOL lazy ) { m_query_func = query_func; - m_version_func = ck_builtin_declversion; + m_api_version_func = ck_builtin_declversion; m_done_query = FALSE; m_func = "ck_query"; @@ -904,18 +904,18 @@ const Chuck_DL_Query * Chuck_DLL::query() return &m_query; // get the address of the DL version function from the DLL - if( !m_version_func ) - m_version_func = (f_ck_declversion)this->get_addr( CK_DECLVERSION_FUNC ); - if( !m_version_func ) - m_version_func = (f_ck_declversion)this->get_addr( (string("_")+CK_DECLVERSION_FUNC).c_str() ); - if( !m_version_func ) + if( !m_api_version_func ) + m_api_version_func = (f_ck_declversion)this->get_addr( CK_DECLVERSION_FUNC ); + if( !m_api_version_func ) + m_api_version_func = (f_ck_declversion)this->get_addr( (string("_")+CK_DECLVERSION_FUNC).c_str() ); + if( !m_api_version_func ) { m_last_error = string("no version function found in dll '") + m_filename + string("'"); return NULL; } // check version - t_CKUINT dll_version = m_version_func(); + t_CKUINT dll_version = m_api_version_func(); // get major and minor version numbers m_versionMajor = CK_DLL_VERSION_GETMAJOR(dll_version); m_versionMinor = CK_DLL_VERSION_GETMINOR(dll_version); @@ -930,10 +930,10 @@ const Chuck_DL_Query * Chuck_DLL::query() { // construct error string ostringstream oss; - oss << "chugin version incompatible..." << endl + oss << "chugin API version incompatible..." << endl << "chugin path: '" << m_filename << "'" << endl - << "chugin version: " << m_versionMajor << "." << m_versionMinor - << " VS host version: " << CK_DLL_VERSION_MAJOR << "." << CK_DLL_VERSION_MINOR; + << "chugin API version: " << m_versionMajor << "." << m_versionMinor + << " VS host API version: " << CK_DLL_VERSION_MAJOR << "." << CK_DLL_VERSION_MINOR; m_last_error = oss.str(); return NULL; } @@ -1069,18 +1069,18 @@ t_CKBOOL Chuck_DLL::probe() } // get the address of the DL version function from the DLL - if( !m_version_func ) - m_version_func = (f_ck_declversion)this->get_addr( CK_DECLVERSION_FUNC ); - if( !m_version_func ) - m_version_func = (f_ck_declversion)this->get_addr( (string("_")+CK_DECLVERSION_FUNC).c_str() ); - if( !m_version_func ) + if( !m_api_version_func ) + m_api_version_func = (f_ck_declversion)this->get_addr( CK_DECLVERSION_FUNC ); + if( !m_api_version_func ) + m_api_version_func = (f_ck_declversion)this->get_addr( (string("_")+CK_DECLVERSION_FUNC).c_str() ); + if( !m_api_version_func ) { m_last_error = string("no version function found in dll '") + m_filename + string("'"); return FALSE; } // check version - t_CKUINT dll_version = m_version_func(); + t_CKUINT dll_version = m_api_version_func(); // get major and minor version numbers m_versionMajor = CK_DLL_VERSION_GETMAJOR(dll_version); m_versionMinor = CK_DLL_VERSION_GETMINOR(dll_version); @@ -1216,8 +1216,10 @@ t_CKBOOL Chuck_DLL::compatible() if( m_versionMajor == CK_DLL_VERSION_MAJOR && m_versionMinor <= CK_DLL_VERSION_MINOR ) { return TRUE; } else { - m_last_error = string("version incompatible with host ") + - ck_itoa(CK_DLL_VERSION_MAJOR) + "." + ck_itoa(CK_DLL_VERSION_MINOR); + m_last_error = string("incompatible API version: chugin (") + ck_itoa(m_versionMajor) + "." + ck_itoa(m_versionMinor) + + string(") vs. host (") + + ck_itoa(CK_DLL_VERSION_MAJOR) + "." + ck_itoa(CK_DLL_VERSION_MINOR) + + ")"; return FALSE; } } diff --git a/src/core/chuck_dl.h b/src/core/chuck_dl.h index b130f0663..e047e3171 100644 --- a/src/core/chuck_dl.h +++ b/src/core/chuck_dl.h @@ -322,6 +322,7 @@ struct Chuck_DL_Arg extern "C" { // query typedef t_CKUINT (CK_DLL_CALL * f_ck_declversion)(); +typedef const char * (CK_DLL_CALL * f_ck_info)( const char * key ); typedef t_CKBOOL (CK_DLL_CALL * f_ck_query)( Chuck_DL_Query * QUERY ); // object typedef Chuck_Object * (CK_DLL_CALL * f_alloc)( Chuck_VM * VM, Chuck_VM_Shred * SHRED, CK_DL_API API ); @@ -764,7 +765,7 @@ struct Chuck_DLL : public Chuck_VM_Object // constructor Chuck_DLL( Chuck_Carrier * carrier, const char * xid = NULL ) : m_handle(NULL), m_id(xid ? xid : ""), - m_done_query(FALSE), m_version_func(NULL), m_query_func(NULL), + m_done_query(FALSE), m_api_version_func(NULL), m_info_func(NULL), m_query_func(NULL), m_query( carrier, this ), m_versionMajor(0), m_versionMinor(0) { } // destructor @@ -779,8 +780,13 @@ struct Chuck_DLL : public Chuck_VM_Object std::string m_func; t_CKBOOL m_done_query; - f_ck_declversion m_version_func; + // host/client api version + f_ck_declversion m_api_version_func; + // chugin info func + f_ck_info m_info_func; + // the query func f_ck_query m_query_func; + // the query shuttle object Chuck_DL_Query m_query; protected: // addition info 1.5.0.4 (ge) added diff --git a/src/core/chuck_errmsg.cpp b/src/core/chuck_errmsg.cpp index 1c8a1a82f..c9cf2c631 100644 --- a/src/core/chuck_errmsg.cpp +++ b/src/core/chuck_errmsg.cpp @@ -821,6 +821,62 @@ void EM_log( t_CKINT level, const char * message, ... ) +//----------------------------------------------------------------------------- +// name: EM_log_opts() +// desc: output log message at a particular log level (no NL) +//----------------------------------------------------------------------------- +void EM_log_opts( t_CKINT level, enum em_LogOpts options, const char * message, ... ) +{ + va_list ap; + + if( level > CK_LOG_ALL ) level = CK_LOG_ALL; + else if( level <= CK_LOG_NONE ) level = CK_LOG_NONE + 1; + + // check level + if( level > g_loglevel ) return; + + // whether to print prefix + t_CKBOOL prefix = !(options & EM_LOG_NO_PREFIX); + // whether to print newline at end + t_CKBOOL nl = !(options & EM_LOG_NO_NEWLINE); + + #ifndef __DISABLE_THREADS__ + g_logmutex.acquire(); + #endif + + // check option + if( prefix ) + { + TC::off(); + CK_FPRINTF_STDERR( "[%s:%s:%s]: ", + TC::blue("chuck", true).c_str(), + TC::blue( ck_itoa(level), false ).c_str(), + TC::blue( g_str[level] ).c_str() ); + TC::on(); + + // if( g_logstack ) CK_FPRINTF_STDERR( " " ); + for( int i = 0; i < g_logstack; i++ ) + CK_FPRINTF_STDERR( " | " ); + } + + va_start( ap, message ); + CK_VFPRINTF_STDERR( message, ap ); + va_end( ap ); + + // print newline + if( nl ) CK_FPRINTF_STDERR( "\n" ); + + // flush + CK_FFLUSH_STDERR(); + + #ifndef __DISABLE_THREADS__ + g_logmutex.release(); + #endif +} + + + + //----------------------------------------------------------------------------- // name: EM_setlog() // desc: set log level diff --git a/src/core/chuck_errmsg.h b/src/core/chuck_errmsg.h index f570f0952..98b53a50e 100644 --- a/src/core/chuck_errmsg.h +++ b/src/core/chuck_errmsg.h @@ -52,6 +52,13 @@ #define CK_LOG_CORE 1 #define CK_LOG_NONE 0 // set this to log nothing +// bitwise options for EM_log_opts +enum em_LogOpts +{ + EM_LOG_NONE = 0, + EM_LOG_NO_NEWLINE = 0x1, + EM_LOG_NO_PREFIX = 0x10 +}; // C linkage #if defined(_cplusplus) || defined(__cplusplus) @@ -66,8 +73,11 @@ extern "C" { #define CK_LOG( level, ... ) do{ if(level <= g_loglevel) \ { EM_log( level, __VA_ARGS__ ); } }while(0) + // output log message void EM_log( t_CKINT, c_constr, ... ); +// output log message (with options) +void EM_log_opts( t_CKINT level, enum em_LogOpts options, c_constr, ... ); // set log level [CK_LOG_NONE, CK_LOG_ALL] void EM_setlog( t_CKINT level ); // push the log indentation