From 3b45e376939377551fdd7e3c3c99ff525d2b7de4 Mon Sep 17 00:00:00 2001 From: Elijah Newren Date: Thu, 4 May 2023 10:02:23 -0700 Subject: [PATCH] WIP script for checking if includes in sources can be removed --- check-header-removal-from-source.rs | 157 ++++++++++++++++++++++++++++ 1 file changed, 157 insertions(+) create mode 100755 check-header-removal-from-source.rs diff --git a/check-header-removal-from-source.rs b/check-header-removal-from-source.rs new file mode 100755 index 00000000000000..318235df18c770 --- /dev/null +++ b/check-header-removal-from-source.rs @@ -0,0 +1,157 @@ +#!/usr/bin/env run-cargo-script +//! ```cargo +//! [dependencies] +//! regex = "1.8.1" +//! ``` +#![allow(unused_imports)] + +extern crate regex; + +use regex::Regex; +use std::env; +use std::fs; +use std::io::{self, Write}; +use std::path::{Path, PathBuf}; +use std::process::{Command, Stdio}; + +fn main() { + let args: Vec = env::args().collect(); + + if args.len() != 2 { + eprintln!("Usage: {} ", args[0]); + std::process::exit(1); + } + + let source_file = &args[1]; + + let source_content = match fs::read_to_string(source_file) { + Ok(content) => content, + Err(err) => { + eprintln!("Failed to read source file '{}': {}", source_file, err); + std::process::exit(1); + } + }; + + let mut includes = Vec::new(); + + for (i, line) in source_content.lines().enumerate() { + if line.trim_start().starts_with("#include") { + includes.push(i); + } + } + + let mut tweaked_line = ""; + + for include_line_number in &includes { + let modified_source_content = { + let mut modified_content = String::new(); + let mut include_commented = false; + + for (i, line) in source_content.lines().enumerate() { + if i == *include_line_number { + if line.trim_start().starts_with("/*") { + include_commented = true; + } else { + modified_content += "//#"; + modified_content += line; + modified_content += "\n"; + tweaked_line = line; + } + } else if include_commented { + if line.trim_start().starts_with("*/") { + include_commented = false; + } + } else { + modified_content += line; + modified_content += "\n"; + } + } + + modified_content + }; + + if !tweaked_line.starts_with("#include \"") { + continue; + } + let filename = tweaked_line.trim_start_matches("#include ") + .trim_matches('"'); + let path = Path::new(filename); + let filename_only = path.file_name().unwrap().to_str().unwrap(); + //println!("Working on {}", filename_only); + + let source_file_path = Path::new(source_file); + // Overwrite source with modified program + if let Err(err) = fs::write(&source_file_path, &modified_source_content) { + eprintln!("Failed to overwrite source file: {}", err); + std::process::exit(1); + } + + let output = Command::new("gcc") + .arg("-E") + .arg("-I.") + .arg(&source_file_path) + .stdin(Stdio::piped()) + .stderr(Stdio::piped()) + .output() + .expect("Failed to run command"); + + let escaped_include = regex::escape(filename_only); + let pattern_str = format!("\\b{}\"", escaped_include); + let regex = Regex::new(&pattern_str).unwrap(); + let stdout = String::from_utf8(output.stdout).expect("Invalid UTF-8"); + let mut match_found = false; + for line in stdout.lines() { + if regex.is_match(line) { + match_found = true; + break; + } + } + if match_found { + //println!("No point removing {}", filename_only); + Command::new("git") + .arg("checkout") + .arg(&source_file_path) + .stdin(Stdio::piped()) + .stderr(Stdio::piped()) + .output() + .expect("Failed to run command"); + continue; + } + + let object_file = source_file.replace(".c", ".o"); + let output = Command::new("make") + .arg("DEVELOPER=1") + .arg(&object_file) + .stdin(Stdio::piped()) + .stderr(Stdio::piped()) + .output() + .expect("Failed to run command"); + + // Report the success or failure of the compilation + if output.status.success() { + println!("{} compiles without: {}", source_file, tweaked_line); + } else { + /* + println!("Compilation failed after removing include: {}", tweaked_line); + println!("Output: {}\n", String::from_utf8_lossy(&output.stdout)); + println!("Stderr: {}\n", String::from_utf8_lossy(&output.stderr)); + let output = Command::new("git") + .arg("diff") + .arg(&source_file_path) + .stdin(Stdio::piped()) + .stderr(Stdio::piped()) + .output() + .expect("Failed to run command"); + println!("Diff: {}\n", String::from_utf8_lossy(&output.stdout)); + */ + } + + Command::new("git") + .arg("checkout") + .arg(&source_file_path) + .stdin(Stdio::piped()) + .stderr(Stdio::piped()) + .output() + .expect("Failed to run command"); + } +}