diff --git a/main.cpp b/main.cpp index 6316851..a1f9abf 100644 --- a/main.cpp +++ b/main.cpp @@ -16,6 +16,25 @@ enum class OutputFormat Sarif }; +static void printHelp() +{ + llvm::outs() + << "Stack Usage Analyzer - static stack usage analysis for LLVM IR/bitcode\n\n" + << "Usage:\n" + << " stack_usage_analyzer [options]\n\n" + << "Options:\n" + << " --mode=ir|abi Analysis mode (default: ir)\n" + << " --format=json Output JSON report\n" + << " --format=sarif Output SARIF report\n" + << " --quiet Suppress per-function diagnostics\n" + << " --warnings-only Show warnings and errors only\n" + << " -h, --help Show this help message and exit\n\n" + << "Examples:\n" + << " stack_usage_analyzer input.ll\n" + << " stack_usage_analyzer input.ll --mode=abi --format=json\n" + << " stack_usage_analyzer input.ll --warnings-only\n"; +} + int main(int argc, char **argv) { llvm::LLVMContext context; @@ -30,6 +49,15 @@ int main(int argc, char **argv) // cfg.mode = AnalysisMode::IR; -> already set by default constructor // cfg.stackLimit = 8ull * 1024ull * 1024ull; // 8 MiB -> already set by default constructor but needed to be set with args + for (int i = 1; i < argc; ++i) + { + if (std::strcmp(argv[i], "-h") == 0 || std::strcmp(argv[i], "--help") == 0) + { + printHelp(); + return 0; + } + } + for (int i = 1; i < argc; ++i) { const char *arg = argv[i]; @@ -54,6 +82,11 @@ int main(int argc, char **argv) outputFormat = OutputFormat::Sarif; continue; } + else if (argStr == "--format=human") + { + outputFormat = OutputFormat::Human; + continue; + } if (std::strncmp(arg, "--mode=", 7) == 0) { const char *modeStr = arg + 7; @@ -77,7 +110,8 @@ int main(int argc, char **argv) } if (!inputFilename) { - llvm::errs() << "Usage: stack_usage_analyzer [--mode=ir|abi]\n"; + llvm::errs() << "Usage: stack_usage_analyzer [options]\n" + << "Try --help for more information.\n"; return 1; } diff --git a/run_test.py b/run_test.py index 484e0e1..237d1a9 100755 --- a/run_test.py +++ b/run_test.py @@ -78,6 +78,36 @@ def run_analyzer_on_file(c_path: Path) -> str: return output +def check_help_flags() -> bool: + """ + Vérifie que -h et --help affichent l'aide sur stdout et retournent 0. + """ + print("=== Testing help flags ===") + ok = True + for flag in ["-h", "--help"]: + result = subprocess.run( + [str(ANALYZER), flag], + capture_output=True, + text=True, + ) + stdout = result.stdout or "" + if result.returncode != 0: + print(f" ❌ {flag} returned {result.returncode} (expected 0)") + ok = False + continue + missing = [] + for needle in ["Stack Usage Analyzer", "Usage:", "Options:", "-h, --help", "Examples:"]: + if needle not in stdout: + missing.append(needle) + if missing: + print(f" ❌ {flag} missing help sections: {', '.join(missing)}") + ok = False + else: + print(f" ✅ {flag} OK") + print() + return ok + + def check_file(c_path: Path) -> bool: """ Vérifie qu'avec ce fichier, toutes les attentes sont présentes @@ -112,12 +142,13 @@ def check_file(c_path: Path) -> bool: def main() -> int: + global_ok = check_help_flags() + c_files = sorted(TEST_DIR.glob("**/*.c")) if not c_files: print(f"No .c files found under {TEST_DIR}") - return + return 0 if global_ok else 1 - global_ok = True for f in c_files: ok = check_file(f) if not ok: