mirror of
https://gitlab.kitware.com/cmake/cmake.git
synced 2026-09-25 04:09:36 +03:00
IAR: Add post-processing step in C-STAT outputs
Harmonize IAR C-STAT headers between the first-time analysis and subsequent builds, which uses cached results. It also removes spurious relative paths such as `"../` and `..\` that might appear after a new line followed by a double quote. Effectively this will display paths relative to CMAKE_SOURCE_DIR, similarly to the IDE, which display paths relative to $PROJ_DIR$. Update the IAR tests to match the new C-STAT outputs.
This commit is contained in:
+41
-4
@@ -654,13 +654,50 @@ int HandleIcstat(std::string const& runCmd, std::string const& sourceFile,
|
||||
// Run the IAR C-STAT command line. Capture its output.
|
||||
if (!cmSystemTools::RunSingleCommand(icstat_cmd, &stdOut, &stdErr, &ret,
|
||||
nullptr, cmSystemTools::OUTPUT_NONE)) {
|
||||
std::cerr << "Error running '" << icstat_cmd[0] << "': " << stdOut << '\n';
|
||||
std::cerr << "C-STAT: Error running '" << icstat_cmd[0] << "': " << stdOut
|
||||
<< '\n';
|
||||
return 1;
|
||||
}
|
||||
|
||||
// Post-process successful output for consistent messaging and path cleanup.
|
||||
if (ret == 0) {
|
||||
std::cerr << "Warning: C-STAT static analysis reported diagnostics:\n";
|
||||
} else {
|
||||
std::cerr << "Error: C-STAT static analysis reported failure:\n";
|
||||
// Harmonize IAR C-STAT headers between the first-time analysis
|
||||
// and subsequent builds that use cached results.
|
||||
std::cerr << "C-STAT: ";
|
||||
if (stdOut.find("Analyzing") == std::string::npos) {
|
||||
std::string prepend;
|
||||
prepend =
|
||||
cmStrCat("Analyzing ", cmSystemTools::GetFilenameName(sourceFile),
|
||||
" (cached)\n");
|
||||
stdOut.insert(0, prepend);
|
||||
}
|
||||
|
||||
// Single-pass removal of consecutive spurious relative paths,
|
||||
// `"../` or `"..\`, that might appear after a newline followed by
|
||||
// an opening quote, effectively displaying paths relative to
|
||||
// CMAKE_SOURCE_DIR.
|
||||
// Example: `\n"../../../src/file.c` -> `\n"src/file.c`
|
||||
std::string cleaned;
|
||||
size_t const n = stdOut.size();
|
||||
cleaned.reserve(n);
|
||||
size_t pos = 0;
|
||||
while (pos < n) {
|
||||
if (pos + 1 < n && stdOut[pos] == '\n' && stdOut[pos + 1] == '"') {
|
||||
cleaned += "\n\"";
|
||||
pos += 2; // skip `\n"`
|
||||
|
||||
while (pos + 2 < n && stdOut[pos] == '.' && stdOut[pos + 1] == '.' &&
|
||||
(stdOut[pos + 2] == '/' || stdOut[pos + 2] == '\\')) {
|
||||
pos += 3; // skip `../` or `..\`
|
||||
}
|
||||
} else {
|
||||
cleaned += stdOut[pos];
|
||||
++pos;
|
||||
}
|
||||
}
|
||||
stdOut.swap(cleaned);
|
||||
} else if (ret != 0) {
|
||||
std::cerr << "C-STAT ";
|
||||
}
|
||||
std::cerr << stdOut;
|
||||
std::cerr << stdErr;
|
||||
|
||||
@@ -1,3 +1,3 @@
|
||||
Error: C-STAT static analysis reported failure:
|
||||
stdout from bad command line arg '-bad'
|
||||
stderr from bad command line arg '-bad'
|
||||
C-STAT Command line error: Unexpected command line arguments:
|
||||
-bad
|
||||
-bad
|
||||
|
||||
@@ -1,2 +1 @@
|
||||
Warning: C-STAT static analysis reported diagnostics.*C-STAT analyze source: [^
|
||||
]*module\.c.*Severity
|
||||
C-STAT: Analyzing module.c.*Severity
|
||||
|
||||
@@ -1,3 +1,3 @@
|
||||
Error: C-STAT static analysis reported failure:
|
||||
stdout from bad command line arg '-bad'
|
||||
stderr from bad command line arg '-bad'
|
||||
C-STAT Command line error: Unexpected command line arguments:
|
||||
-bad
|
||||
-bad
|
||||
|
||||
@@ -1,2 +1 @@
|
||||
Warning: C-STAT static analysis reported diagnostics.*C-STAT analyze source: [^
|
||||
]*module\.cxx.*Severity
|
||||
C-STAT: Analyzing module.cxx.*Severity
|
||||
|
||||
@@ -2,6 +2,21 @@
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
|
||||
char const* get_filename(char const* path)
|
||||
{
|
||||
// Find the last occurrence of '/'
|
||||
char const* last_slash = strrchr(path, '/');
|
||||
|
||||
// If not found, try finding the last occurrence of '\'
|
||||
if (!last_slash) {
|
||||
last_slash = strrchr(path, '\\');
|
||||
}
|
||||
|
||||
// If a separator was found, return the character after it
|
||||
// Otherwise, return the original path (no directory component)
|
||||
return last_slash ? last_slash + 1 : path;
|
||||
}
|
||||
|
||||
int main(int argc, char* argv[])
|
||||
{
|
||||
int i;
|
||||
@@ -9,15 +24,18 @@ int main(int argc, char* argv[])
|
||||
char const* source = "";
|
||||
for (i = 1; i < argc; ++i) {
|
||||
if (strcmp(argv[i], "-bad") == 0) {
|
||||
fprintf(stdout, "stdout from bad command line arg '-bad'\n");
|
||||
fprintf(stderr, "stderr from bad command line arg '-bad'\n");
|
||||
fprintf(
|
||||
stdout,
|
||||
"C-STAT Command line error: Unexpected command line arguments:\n");
|
||||
fprintf(stdout, " -bad\n");
|
||||
fprintf(stderr, " -bad\n");
|
||||
return 1;
|
||||
}
|
||||
if (strcmp(argv[i], "analyze") == 0 && i + 1 < argc) {
|
||||
source = argv[++i];
|
||||
if (strcmp(argv[i], "--silent") == 0 && (i + 1) < argc) {
|
||||
source = get_filename(argv[++i]);
|
||||
}
|
||||
}
|
||||
fprintf(stderr, "C-STAT analyze source: %s\n", source);
|
||||
fprintf(stderr, "C-STAT: Analyzing %s\n", source);
|
||||
fprintf(stderr,
|
||||
"\"foo/bar.c\",2 Severity-High[SPC-uninit-var-some]:"
|
||||
"Variable `i' may be uninitialized.\n\n");
|
||||
|
||||
Reference in New Issue
Block a user