⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 trace.cxx

📁 eCos1.31版
💻 CXX
📖 第 1 页 / 共 2 页
字号:
    tracevec[i].valid   = true;    if (!callback_installed) {        cyg_assert_install_failure_callback("Trace", &trace_callback);        callback_installed = true;    }}//}}}//{{{  Output callback                                  // ----------------------------------------------------------------------------// Dumping the output. The assertion code will invoke a single callback// function, cyg_trace_dummy::trace_callback(), with a function pointer// that can be used for the actual output.//// The trace_callback() function loops through the various entries in the// vector, ignoring invalid ones, and invoking output_entry() for the// valid ones.//// There are a number of utility routines:////     trim_file() is used to take a full pathname and return just the//     final part of it as a C++ string. There is an upper bound on the//     length of this string.////     trim_linenum() formats the linenumber sensibly.////     trim_function() is used to parse a __PRETTY_FUNCTION__ value//     and produce something more manageable.////     parse_msg() is used to construct the full trace message.//     Because of possible 32/64 bit confusion it is not possible//     to just use sprintf() for this.static std::stringtrim_file(char* file){    // If the output is to look reasonable then the result should be a    // fixed length. 20 characters is reasonable for now.    const int max_filename_len = 20;        if (0 == file) {        return std::string(max_filename_len, ' ');    }    // Move to the end of the string, and then back again until    // a directory separator is found. Given the number of levels    // in a typical eCos directory hierarchy it is probably not    // worthwhile outputting any of that information.    char * pEnd = file + strlen(file);    while ((pEnd > file) && ('/' != *pEnd) && ('\\' != *pEnd)) {        pEnd--;    }    if (pEnd != file)        pEnd++;    std::string result = "";    int         i      = 0;    for ( ;(*pEnd != '\0') && (i < max_filename_len); i++, pEnd++) {        result += *pEnd;    }    for ( ; i < max_filename_len; i++) {        result += ' ';    }    return result;}// The linenumber output should be up to four digits, right-padded// with spaces. sprintf() will do the trick nicely.static std::stringtrim_linenum(cyg_uint32 line){    char buf[32];    sprintf(buf, "%-4d", (int) line);    return buf;}// Extract a function name. On the target side function names// are usually obtained via __PRETTY_FUNCTION__, and the resulting// output is a bit on the large side: return value, arguments, etc// are all included. On the host side the function name is normally// supplied explicitly and should not be trimmed at all.//// Padding is not appropriate since the function name is likely// to be followed immediately by the argument list. No maximum// length is imposed - arguably that is a bad idea.static std::stringtrim_function(char* fn){    if (0 == fn) {        return "<unknown>";    }#if 1    return fn;#else    // This implements the target-side behaviour.    //    // First locate the opening bracket. The function name can    // be identified by walking backwards from that.    char *s;    for (s = fn; ('\0' != *s) && ('(' != *s); s++);    for ( ; (s > fn) && (*s != ' '); s--);    if ( s > fn) s++;    std::string result = "";    while ( ('\0' != *s) && ('(' != *s) )        result += *s++;    return result;#endif}// The trace format string contained a %s. It is necessary to check// whether the argument is still valid, and return a suitable// approximation to the actual data.static std::stringtrim_string(char * arg){    const int max_string_len = 20;    std::string result = "";    if (0 == arg) {        return result;    }    int i;    for ( i = 0; (i < max_string_len) && ('\0' != *arg) && isprint(*arg); i++, arg++) {        result += *arg;    }    return result;}// ----------------------------------------------------------------------------// Parse a printf() style format string and do the appropriate expansions.// Because of possible confusion between 32 and 64 bit integers it is not// possible to use sprintf() itself.//// It is assumed that the format string is valid, as are most of the// arguments. The possible exception is %s arguments where a little bit of// checking happens first.static std::stringparse_msg(char* msg, trace_entry& entry){    if (0 == msg) {        return "";    }    // Keep track of the number of arguments in the trace_entry    // that have been processed.    int args_index = 0;    // A utility buffer for sprintf(), e.g. for integer-> string conversions.    char util_buf[64];        std::string result = "";    for ( ; '\0' != *msg; msg++) {                if ('%' != *msg) {            result += *msg;            continue;        }        // We have a format string. Extract all of it.        std::string format = "%";        msg++;        // The first part of the format string may be one or more flags.        while ( ('-' == *msg) || ('+' == *msg) || (' ' == *msg) ||                ('#' == *msg) || ('0' == *msg) ) {            format += *msg++;        }        // Next comes the width. If this is an asterix it is necessary to        // substitute in an actual argument.        if ('*' == *msg) {            int width = (args_index < 8) ? (int) entry.data[args_index++] : 0;            sprintf(util_buf, "%d", width);            format += util_buf;            msg++;        } else {            // Otherwise the width should be one or more digits            while( isdigit(*msg) ) {                format += *msg++;            }        }        // Look for a precision, again coping with an asterix.        if ('.' == *msg) {            format += *msg++;            if ('*' == *msg) {                int precision = (args_index < 8) ? (int) entry.data[args_index++] : 0;                sprintf(util_buf, "%d", precision);                format += util_buf;                msg++;            } else {                // The precision should be one or more digits, with an optional -                if ('-' == *msg) {                    format += *msg++;                }                while (isdigit(*msg)) {                    format += *msg++;                }            }        }        // Now look for h,l and L. These have to be remembered.        bool short_version = false;        bool long_version  = false;        if ('h' == *msg) {            format        += *msg++;            short_version  = true;        } else if (('l' == *msg) || ('L' == *msg)) {            format        += *msg++;            long_version   = true;        }        // The end of the format string has been reached.        int format_ch  = *msg;        format        += *msg;        // If we have already formatted too many arguments, there is no point        // in trying to do the actual formatting.        if ( 8 <= args_index ) {            continue;        }        CYG_ADDRWORD val = entry.data[args_index++];        switch( format_ch ) {          case '%' :              result += '%';              break;                        case 'd' :          case 'i' :          case 'o' :          case 'u' :          case 'x' :          case 'X' :               // "format" contains the appropriate format string.              // Invoke sprintf() using util_buf, doing the              // appropriate cast, and then append the output              // of util_buf.              //              // This is not totally robust. If a ridiculous              // precision has been specified then util_buf may              // overflow.              if (long_version) {                  sprintf(util_buf, format.c_str(), (long) val);              } else {                  // The implicit cast rules mean that shorts do not                  // require any special attention.                  sprintf(util_buf, format.c_str(), (int) val);              }              result += util_buf;              break;          case 'c' :              sprintf(util_buf, format.c_str(), (int) val);              result += util_buf;              break;                        case 'p' :              sprintf(util_buf, format.c_str(), (void *) val);              result += util_buf;              break;                        case 's' :          {              std::string data = trim_string((char *) val);              sprintf(util_buf, format.c_str(), data.c_str());              result += util_buf;              break;          }          default :              // Any attempt to do floating point conversions would be              // rather tricky given the casts that have been applied.              // There is no point in doing anything for unrecognised              // sequences.              break;        }    }    return result;}// ----------------------------------------------------------------------------static voidoutput_entry(void (*pOutputFn)(const char*), trace_entry& entry){    std::string output  = trim_file(entry.file)    + " " +                          trim_linenum(entry.line) + " " +                          trim_function(entry.fn)  + " ";    if (0 != entry.msg) {                switch( entry.what) {          case cyg_trace_trace  : output += " '"; break;          case cyg_trace_enter  : output += "{{"; break;          case cyg_trace_args   : output += "(("; break;          case cyg_trace_return : output += "}}"; break;          default               : output += " ?";        }        output += parse_msg(entry.msg, entry);        switch( entry.what) {          case cyg_trace_trace  : output += "' "; break;          case cyg_trace_enter  : break;          case cyg_trace_args   : output += "))"; break;          case cyg_trace_return : break;          default               : output += "? ";        }    }    output += "\n";    (*pOutputFn)(output.c_str());}static voidtrace_callback( void (*pOutputFn)(const char*)){    if ((trace_index < 0) || (trace_index >= CYGNUM_INFRA_TRACE_VECTOR_SIZE))        return;        // Start at the last entry and work back down to zero, skipping    // invalid ones. Then go to the top and work back to the current index.    int i;    for (i = trace_index - 1; i >= 0; i--) {        if (tracevec[i].valid) {            output_entry(pOutputFn, tracevec[i]);        }    }    for (i = (CYGNUM_INFRA_TRACE_VECTOR_SIZE - 1); i >= trace_index; i--) {        if (tracevec[i].valid) {            output_entry(pOutputFn, tracevec[i]);        }    }}//}}}

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -