📄 trace.cxx
字号:
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 + -